AOP, Chinese name, tangent. It's really cool to implement what you want without impacting your business code. This is not, recently came a demand.
Business requirements: Want to record a number of critical business requests and operations! This itself is OK, but these requirements are too regular, we can not hard, or a word low.
AOP is a good thing, and logging is a must.
The same is true for recording data, so it can be done with AOP, and this is where annotations are used to solve the problem.
Because it is a key business, so it means not all business, then naturally think of, you can use the way of filtering, that is, using annotations, if there are annotations then represent to record data, otherwise not recorded.
What does the recording process need to do?
First, because it is recording business data, we can abstract out a method, that is, Xxx.addrec (). That is, just call the recording method in the slice.
So there are a few questions left, how can we find this method? What about parameter handling? Do I need to use a specification limit?
To find this method, we can use reflection calls, which of course require annotations to invoke the class and method name (if fixed dead without labeling), the advantage of reflection is freedom, how to write it, or failure or success. But low!
Parameters can be determined according to the input class, if. else.. And then directly process the corresponding parameters. This can be very free, how to write parameters on how to write parameters. But in this case, this aspect is fully coupled with the business code, and more than n meaningless judgment. Very low!
Then the question comes, how is it not low?
Several theories can be drawn from the following:
1. Interface-oriented programming rather than class-oriented programming;
2. Use the enumeration values for the unified planning of annotations;
3. Use generics to handle the upper and lower parameters;
4. Encapsulating parameters using template method mode;
5. Use the thread pool;
Let's look at the next ~
Interface-oriented programming, which requires all business processing classes to implement a common interface, so that the method is not messy, define a clear interface, more easily understand the meaning. Each implementation class only needs to focus on its own logic.
Using enumeration values for the qualification of annotation parameters allows all business operations to be listed in one place and conform to the required specifications. In addition, when a parameter is found to be unable to meet certain requirements, it is convenient to include the appropriate parameters in the enumeration to complete the requirement.
Use generics to limit parameters to a certain range, such as requiring the inbound parameter must inherit a base class to achieve uniform parameter processing, and also prevent the passing of arbitrary parameters and must do the corresponding conversion performance consumption.
Use template method mode for parameter encapsulation, because in the parameters are required to inherit a base class, that is, have common parameters, so should have the ability to automatically handle the public parameters, but not ultra vires processing of various business implementation, should let the implementation class have the ability to handle personalized parameters (Implementation class can also not handle). When the implementation class handles personalization parameters, it should have absolute ability and should not limit its exertion.
Using thread pooling technology, the extra work is handed over to the extra threads, so that the main business does not love the impact.
Specific code to repeat:
1. Annotations open a new chapter, no annotations, no work.
@Component Public class Usertestservice { // add annotations, which represent the logical processing required @BizRecordTrans (biztype = Bizrecordtypeenum.user_add_flow) public responseentity<boolean> addUser (userldto Terminalreq) { responseentity<Boolean> ret = responsebuilder.buildresponse (); // Finish your business ... return ret; }}
2. Slice configuration, do a behind-the-scenes veteran.
@Component @aspect Public classBIZRECORDAOP {PrivateLogger Logger = Loggerfactory.getlogger ( This. GetClass ()); @Around ("Execution (* com.xxx.dubbo.*.* (..))) and @annotation (Com.xxx.spring.annotation.BizRecordTrans) ") PublicObject deal (Proceedingjoinpoint PJP)throwsthrowable {Object retVal=NULL; String MethodName=pjp.getsignature (). GetName (); Object[] args=Pjp.getargs (); Class<?> Classtarget =pjp.gettarget (). GetClass (); Class<?>[] Argtypes =( (Methodsignature) pjp.getsignature ()). Getparametertypes (); Method Objmethod=Classtarget.getmethod (MethodName, argtypes); Bizrecordtrans Bizrecordtrans= Objmethod.getannotation (Bizrecordtrans.class); Bizrecordtypeenum Bizrecordtypeenum=NULL; if(Bizrecordtrans! =NULL) {Bizrecordtypeenum=Bizrecordtrans.biztype (); } Try{RetVal=pjp.proceed (); } Catch(Exception e) {//Ignore Throwe; } finally { if(Bizrecordtrans! =NULL) {Class<?extendsSvcbaseentity> bizrecentitycls =bizrecordtypeenum.getbizrecentitycls (); Svcbaseentity recentity=(svcbaseentity) bizrecentitycls.newinstance (); if(Args[0]instanceofbasedto) {basedto Basedto= (basedto) args[0]; Fillbasefields (recentity, basedto); } Try{Threadpooltaskexecutor Executor= (threadpooltaskexecutor) springcontextsutil.getbean ("Threadpooltaskexecutor"); Executor.execute (()-{Bizrecbaseservice<BaseEntity> Recservice = (bizrecbaseservice<svcbaseentity>) springcontextsutil. Getbean (Bizrecordtypeenum.gethandlerbeanname ()); Recservice.fitownparams (recentity, args); Recservice.addrecord (recentity); }); } Catch(Exception e) {logger.error ("Exception occurred", E); } } } returnRetVal; } /*** Fill Public parameters*/ Private voidFillbasefields (baseentity baseentity, basedto base) {Baseentity.setuserid (Base.getuserid ()); Baseentity.setseqid (Base.getseqid ()); Baseentity.setaddip (Base.getaddip ()); }}
3. Write a basic interface for the business to achieve.
Public Interface extends Baseentity> { /** * Execute business method */Public Integer AddRecord (T bizrecord); /** * Personalized parameter fill method, selective implementation * /defaultvoid fixownparams (T Bizrecord, object[] rawdata) { System.out.println ("Can not be implemented");} }
4. Write a basic class that allows all other business entities to inherit to implement the encapsulation of the common parameters.
@Data Public classsvcbaseentity {/*** ID*/ PrivateLong ID; /*** User ID*/ PrivateLong userId; /*** Request sequence ID*/ PrivateString seqId; /*** Add IP*/ PrivateString Addip; }
5. Play a combo fist and fix it.
The principle is simple and easy to understand. Performance, also OK, don't worry too much.
Hey! Every strange business is an opportunity for practice.
SPRINGAOP to record critical business requests