Custom annotations Implement data caching and timed overload __java

Source: Internet
Author: User
Tags static class

In the company's actual project, there is a program that has a lot of configuration in the T_config table of the database, which makes it easy for the operator to modify these configurations through the front page.

The early developers did not cache the table, and each transaction was read in real time to the corresponding configuration in the database.

As the volume of business continues to increase, the discovery of lower performance, after the investigation is found to be too frequent read the database,

Because the company temporarily does not access Redis technology, so we wrote some cache and overload caching methods, these frequently read database information cached in memory, speed up reading speed, reduce database operation


Here is a brief introduction to this scenario, first of all, the table structure

CREATE TABLE ' t_config ' (
  ' ID ' int () NOT NULL auto_increment,
  ' NAME ' varchar ' is not NULL,
  ' DATA ' varchar (2 Default NULL,
  ' remark ' varchar (255) default NULL,
  PRIMARY KEY (' ID ')


The corresponding JavaBean

public class Tconfig implements Serializable, cloneable {
	private static final long Serialversionuid = 161981168413879 1L;
	Private Long ID;
	private String name;
	Private String data;
	Private String remark;
	..................
	
	the mapping public
	static class Tconfigmapper implements Rowmapper<tconfig> {

		for Get set and constructor//jdbctemplate is omitted Public Tconfig Maprow (ResultSet rs, int index) throws SQLException {tconfig
			tconfig = new Tconfig ();
			
			Long id = rs.getlong ("id");
			Tconfig.setid (ID);

			String name = rs.getstring ("name");
			Tconfig.setname (name);
			
			String data = rs.getstring ("data");
			Tconfig.setdata (data);
			
			String Remark = rs.getstring ("remark");
			Tconfig.setremark (remark);

			return tconfig;
		}

	}



The project uses a mysql,jre version of 1.7,spring4.3.4, and ORM uses Spring's jdbctemplate, the data source is C3P0


Next, the note, which is simple, has only two fields, name is name in the database, and does not specify the name of the current property that is implied

Import Java.lang.annotation.ElementType;
Import java.lang.annotation.Retention;
Import Java.lang.annotation.RetentionPolicy;
Import Java.lang.annotation.Target;

@Target (Elementtype.field)
@Retention (retentionpolicy.runtime) public
@interface Tconfigcache {

	String name () default "";
	
	/**
	 * overload interval, the unit is minutes, the default 5 minutes, the minimum is 1 minutes
	 * 
	 *
	 @return
	/int intervaltime () default 5;
}



Let's take a look at these test data stored in the database




Next is Configsfromdb, all of the database configuration is in this abstract class, this class just declare the variable, and specify the Get method, do not care about how the variable is assigned and timed overload, note the value of the image and the database data

Public abstract class Configsfromdb {
	@TConfigCache
	private String is_send;

	@TConfigCache
	private int start_time;//supports basic data types
	
	@TConfigCache
	private Integer end_time;

	@TConfigCache (name = "Threshold_amount", IntervalTime = 1)
	private Double qidianjine;//Start amount
	
	Private String String Normal properties, not annotated
	
	/**
	 * After loading data callback, can do some of the cleanup work, but not the necessary
	 * *
	protected void Afterload () {
		if ( Qidianjine = = null) {
			qidianjine = 0.0
		;
	}
	
	} /**
	 * After loading data is recalled, do some data validation check, but not required
	 * @return
	/protected Boolean checkdata () {
		if (start_ Time >= end_time) {return
			false;
		}
		return true;
	}

	Public String Getis_send () {return
		is_send;
	}

	Public Integer Getstart_time () {return
		start_time;
	}

	Public Integer Getend_time () {return
		end_time;
	}

	Public Double Getqidianjine () {return
		qidianjine;
	}

	public string getString () {return
		string;
	}
}


Next is the play, Configsfromdbimpl, inherits the Configsfromdb, uses to identify Tconfigcache annotations, and assigns values to these attributes, timed overloads, etc.

Import Java.lang.reflect.Field;
Import java.util.ArrayList;
Import Java.util.HashMap;
Import java.util.List;

Import Java.util.Map;

Import javax.annotation.PostConstruct;
Import org.springframework.beans.factory.annotation.Autowired;
Import Org.springframework.jdbc.core.JdbcTemplate;
Import org.springframework.scheduling.annotation.Scheduled;


Import Org.springframework.stereotype.Repository; @Repository ("Configs") public class Configsfromdbimpl extends Configsfromdb {@Autowired private jdbctemplate Jdbctempla

	Te

	Private list<myfield> fields = new arraylist<myfield> ();

	Private final String SQL = "SELECT * from T_config"; 

	/** * Basic Data type boxing class name conversion/final private static map<string, string> Type_map = new hashmap<string, string> ();
		static {type_map.put ("int", Integer.class.getSimpleName ());
		Type_map.put ("Double", Double.class.getSimpleName ());
		Type_map.put ("Short", Short.class.getSimpleName ()); Type_map.put ("Long", Long.class.getSimpleName ());
		Type_map.put ("Byte", Byte.class.getSimpleName ());
		Type_map.put ("float", Float.class.getSimpleName ());
		Type_map.put ("Boolean", Boolean.class.getSimpleName ());
	Type_map.put ("Char", Character.class.getSimpleName ());
		@PostConstruct private void Init () throws Exception {Initanno ();
		if (!load ()) {///throws Exception, the spring initialization fails and the program fails to start throw new Exception ("Initialization configsfromdb failure, program cannot start");
		} private Boolean Load () throws Exception {//Load data, and assign System.out.println ("Start Loading Database Configuration table");
		Long starttime = System.currenttimemillis (); list<tconfig> configs = jdbctemplate.query (sql, New Tconfig.tconfigmapper ())//execute SQL, full table query int length = Fields.siz
		E ();
			for (int i = 0; i < length; i++) {MyField MyField = Fields.get (i);
			Field field = Myfield.field;
			Tconfigcache anno = field.getdeclaredannotation (Tconfigcache.class);
			String name = Field.getname (); if (! "".
			Equals (Anno.name ())) {//If the name of the annotation is not empty, take the name of the annotation = Anno.name (); } if (Istimeout (MyfiEld, Anno.intervaltime ()) {//To determine if timeout for (Tconfig config:configs) {if (Config.getname (). Equals (name)) { SetValue (field, Config.getdata ()); Assign a value to a property MyField = new MyField (field, System.currenttimemillis ());  Re-setting time Fields.set (I, MyField);  Put back the original position Configs.remove (config);
						Removed from the current database query results to reduce the number of subsequent traversal System.out.println (Field.getname () + "Get the database value of" +config.getdata ());
					Break
				}} else {System.out.println (Field.getname () + "Property not timed out, no overload required");
			Continue } afterload ();
		Callback Data post-processing method SYSTEM.OUT.PRINTLN ("Load Database configuration table end, time consuming:" + (System.currenttimemillis ()-starttime)); return Checkdata (); Callback data checking method} private void Initanno () {//is looking for a property for Tconfig annotation (Field field:this.getClass (). Getsuperclass (). getdecl
			Aredfields ()) {field.setaccessible (true); 
				if (Field.isannotationpresent (Tconfigcache.class)) {//Judge is Tconfigcache annotation MyField MyField = new MyField (field, 0);
				Fields.Add (MyField); System.out.prinTLN ("successfully identified to" + field.getname () + "attribute annotated"); /** * Assigns a value to a property, and can do the corresponding String conversion based on the type of the different attribute/private void setValue (Field field, String value) throws Illegalacce
		ssexception {String type = Field.gettype (). Getsimplename ();
		if (Field.gettype (). Isprimitive ()) {//Judge whether it is a basic data type such as Int,long, then obtain its boxed type = Type_map.get (type);
			Switch (type) {//note jdk1.7 above only supports this syntax case "Integer": Field.set (this, integer.parseint (value));
		Break
			Case "Double": Field.set (this, double.parsedouble (value));
		Break
			Case ' short ': Field.set (this, short.parseshort (value));
		Break
			Case "Long": Field.set (this, Long.parselong (value));
		Break
			Case "Byte": Field.set (this, byte.parsebyte (value));
		Break
			Case "Character": Field.set (this, value);
		Break Case "Boolean": Field.set (this, Boolean.parseboolean (value));
		For this conversion, you can add additional customizations, such as 1 or on to represent the true break;
		You can continue to add a conversion with string type, such as date, BigInteger, Default:field.set (this, value); }}/** * judgmentDoes this attribute timeout * * @param myField * @return/private Boolean istimeout (MyField myField, int intervaltime) {long L
		Astloadtime = Myfield.lastloadtime;
		if (System.currenttimemillis () < (lastloadtime + intervaltime * 1000)) {return false;
	return true;
		@SuppressWarnings ("unused") private class MyField {//field is simply encapsulated so that it has the "last Load Time" property field field;

		Long lastloadtime = 0;
			Public MyField (Field field, Long Lastloadtime) {super ();
			This.field = field;
		This.lastloadtime = Lastloadtime;
			Public MyField (Field field) {super ();
		This.field = field;
		Public MyField () {super ();  }/** * Timed load Data * @throws Exception/@Scheduled (fixeddelay = 1 * 1000, InitialDelay = 2 * 60 * 1000)//
		1 minutes timed up, initial set up dormant 2 minutes private void Loadbytime () throws Exception {System.out.println ("@Scheduled Start overloading Data");
		Load ();
	System.out.println ("@Scheduled Start overloading Data completion"); }
}


Finally, use the demo

Import Org.springframework.context.ApplicationContext;
Import Org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {public

	static void Main (string[] args) throws Throwable {
		ApplicationContext applicationconte XT = new Classpathxmlapplicationcontext ("./config/applicationcontext.xml");

		Final Configsfromdb configs = (configsfromdb) applicationcontext.getbean ("configs");
		
		The new Thread () {//timed print cache data public
			void run () {while
				(true) {
					System.out.println ("-----------------");
					System.out.println (Configs.getis_send ());
					System.out.println (Configs.getstart_time ());
					System.out.println (Configs.getend_time ());
					System.out.println (Configs.getqidianjine ());
					System.out.println ("-----------------");
					try {Sleep
						(1000);
					} catch (Interruptedexception e) {
						e.printstacktrace ();}}
					}
			;
		}.start ();
		
	}


The first execution results, the first execution requires creating a database connection, and so on, so it's slow and time-consuming





After the first time, I modified the database data, so that the starting amount to 9.99, after the scheduled task execution, you can see the printed information as follows



You can see that the starting amount has been modified successfully, the cache is also refreshed correctly, and the reload time is significantly less than the first

After the program is stabilized, what new configuration needs to be added, directly in the Configsfromdb class, new properties, specify the Get method, Configsfromdbimpl basically do not need to modify, so as to reduce the number of new configuration resulting in code writing, After all, laziness is the source of progress.



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.