Annotation-based configuration and use of spring AOP-reproduced

Source: Internet
Author: User
Tags first string getmessage log log

AOP is the continuation of OOP and is the abbreviation for Aspect oriented programming, meaning aspect-oriented programming. A technology that can dynamically and uniformly add functionality to a program without modifying source code is possible through precompilation and run-time dynamic proxies. AOP is actually a continuation of the GOF design pattern, and the design pattern pursues the decoupling between the caller and the callee, and AOP can be said to be an implementation of this goal.

Some of the non-business things we do now, such as logs, transactions, security, and so on, are written in business code (i.e., these non-business classes are crosscutting to the business Class), but the code is often repetitive, and copying--the pasted code is inconvenient for the maintenance of the program, and AOP realizes separating these business requirements from the system requirements. This solution is also called the proxy mechanism.

To understand the concepts of AOP, the Spring reference manual defines the following important concepts of AOP, which are analyzed in conjunction with the above code:

  • Aspect (Aspect): The official abstraction is defined as "a focus of modularity, this concern may be crosscutting multiple objects", in this case, "tangent" is the specific behavior of the class Testaspect, for example, Aserviceimpl.bara () Call is one of the behaviors that the tangent testaspect is concerned about. "Slices" are configured in the ApplicationContext <aop:aspect>.
  • connection point (Joinpoint) : A behavior that is performed during the execution of a program, such as a call to a userservice.get or a userservice.delete throwing an exception.
  • notification (Advice) : The action that "slice" produces for a "connection point", for example, the action of logging the methods of all classes under the Com.spring.service package in Testaspect is a Advice. Where a "slice" can contain multiple "Advice", such as Serviceaspect.
  • pointcut (Pointcut) : An assertion that matches a connection point, a notification in AOP, and a Pointcut expression association. For example, all the notifications in Testaspect are concerned with connection points that are execution by pointcut expressions (* com.spring.service.*.* (..)) to decide.
  • target Object : An object that is notified by one or more facets. For example, Aservcieimpl and Bserviceimpl, of course, when actually running, Spring AOP takes the proxy implementation, the actual AOP operation is TargetObject proxy object.
  • AOP Proxy : There are two kinds of proxy methods in spring AOP, JDK dynamic agent and cglib agent. By default, when the TargetObject implements an interface, the JDK dynamic agent is used, for example, Aserviceimpl; Conversely, cglib proxies, for example, Bserviceimpl. Forcing the Cglib agent to use the Proxy-target-class property of <aop:config> is set to true.

Notification (Advice) type:

    • Forward notification (before advice): A notification that was executed before a connection point (Joinpoint), but this notification does not prevent execution before the connection point. The ApplicationContext uses <aop:before> elements to declare in <aop:aspect>. For example, the Dobefore method in Testaspect.
    • Post notification (after advice): the notification that is executed when a connection point exits (whether it is a normal return or an unexpected exit). The ApplicationContext uses <aop:after> elements to declare in <aop:aspect>. For example, the Returnafter method in Serviceaspect, so the Returnafter method is still executed when Userservice.delete throws an exception in Teser.
    • Notification after return (after return advice): A notification that is executed after a connection point has completed normally, and does not include cases where an exception was thrown. The ApplicationContext uses <after-returning> elements to declare in <aop:aspect>.
    • Wrapping Notification (Around advice): A notification that surrounds a connection point, similar to the Dofilter method of the filter in the servlet specification in the Web. You can customize the behavior before and after the call to the method, or you can choose not to execute. The ApplicationContext uses <aop:around> elements to declare in <aop:aspect>. For example, the around method in Serviceaspect.
    • Notification After an exception is thrown (after throwing advice): the notification that is executed when the method throws an unexpected exit. The ApplicationContext uses <aop:after-throwing> elements to declare in <aop:aspect>. For example, the Returnthrow method in Serviceaspect.

Note: Multiple notifications can be applied to a target object, that is, multiple facets can be woven into the same target object.

The use of spring AOP can be based on two ways, one is more convenient and powerful annotation, the other is a good way to configure the XML.

The first step is to declare the active auto-scan component function in the XML file and activate the automatic proxy feature (while adding a userservice common service layer component to the XML to test the annotation functionality of AOP):

 <?xml version= "1.0" encoding= "UTF-8"? ><beans xmlns= "Http://www.springframework.org/schema/beans" Xmlns:xsi= "Http://www.w3.org/2001/XMLSchema-instance" xmlns:context= "http://www.springframework.org/schema/ Context "xmlns:aop=" HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP "xsi:schemalocation="/HTTP/ WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP http://www.springframework.org/schema/aop/spring-aop-3.1.xsdhttp:// Www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp:// Www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd " ><!--Activate component scanning to automatically scan the components configured via annotations under Package CN.YSH.STUDIO.SPRING.AOP and its sub-packages--><context:component-scan base-package= "CN.YSH.STUDIO.SPRING.AOP"/><!--Activate automatic proxy function--><aop:aspectj-autoproxy proxy-target-class= "true"/> <!--User Service object--><bean id= "UserService" class= "Cn.ysh.studio.spring.aop.service.UserService"/></beans 

The second step is to add annotations to the Aspect slice class:

Package Cn.ysh.studio.spring.aop.aspect;import Org.apache.commons.logging.log;import Org.apache.commons.logging.logfactory;import Org.aspectj.lang.joinpoint;import Org.aspectj.lang.proceedingjoinpoint;import Org.aspectj.lang.annotation.after;import Org.aspectj.lang.annotation.afterreturning;import Org.aspectj.lang.annotation.afterthrowing;import Org.aspectj.lang.annotation.around;import Org.aspectj.lang.annotation.aspect;import Org.aspectj.lang.annotation.before;import Org.aspectj.lang.annotation.pointcut;import org.springframework.stereotype.component;/** * System Services Component Aspect slice Bean * @author shenghany * @date 2013-5-28 */// Declares that this is a component @component//declaration this is a facet Bean@aspectpublic class Serviceaspect {Private final static log log = Logfactory.getlog ( Serviceaspect.class);//Configuration Pointcut, this method has no method body, mainly for the convenience of other methods in the same class using the pointcut configured here @pointcut ("Execution (* Cn.ysh.studio.spring.aop.service. *(..))") public void aspect () {}/* * Configures a pre-notification, using a Pointcut registered on method aspect () * Accepts Joinpoint pointcut objects at the same time, can not have this parameter */@Before ("aspect ()") public void Before (JoinpointJoinpoint) {if (log.isinfoenabled ()) {Log.info ("before" + Joinpoint);}} Configure the post notification using the Pointcut registered on method aspect () @after ("aspect ()") public void After (Joinpoint joinpoint) {if (log.isinfoenabled ()) { Log.info ("after" + Joinpoint);}} Configure the surround notification using the Pointcut registered on method aspect () @around ("aspect ()") public void Around (Joinpoint joinpoint) {Long start = System.currenttimemillis (); try {((proceedingjoinpoint) joinpoint). proceed (); Long end = System.currenttimemillis (); if (log.isinfoenabled ()) {Log.info ("around" + Joinpoint + "\tuse Time:" + (End-start) + "ms!");}} catch (Throwable e) {Long end = System.currenttimemillis (), if (log.isinfoenabled ()) {Log.info ("around" + Joinpoint + "\tus E Time: "+ (End-start) +" Ms with exception: "+ E.getmessage ());}} Configure the post-return notification, using the Pointcut @afterreturning ("aspect ()") registered on method aspect (), public void Afterreturn (Joinpoint joinpoint) {if ( Log.isinfoenabled ()) {Log.info ("Afterreturn" + Joinpoint);}} The configuration throws an exception after notification, using a Pointcut registered on method aspect () @afterthrowing (pointcut= "aspect ()", throwing= "ex") public void Afterthrow (JOINPOint Joinpoint, Exception ex) {if (log.isinfoenabled ()) {Log.info ("Afterthrow" + joinpoint + "\ T" + ex.getmessage ());}}} 

Test code:

Package Cn.ysh.studio.spring.aop;import Org.apache.commons.logging.log;import Org.apache.commons.logging.logfactory;import Org.springframework.context.applicationcontext;import Org.springframework.context.support.classpathxmlapplicationcontext;import Cn.ysh.studio.spring.aop.service.userservice;import cn.ysh.studio.spring.mvc.bean.user;/** * Spring AOP Test * @author Shenghany * @date 2013-5-28 */public class Tester {Private final static log log = Logfactory.getlog (tester.class);p ublic s tatic void Main (string[] args) {//Start spring container applicationcontext context = new Classpathxmlapplicationcontext (" Applicationcontext.xml ");//Get service component UserService Service = (userservice) context.getbean (" UserService ");// The three methods of invoking the UserService object in a normal manner are user user = Service.get (1L), Service.save (user), try {service.delete (1L);} catch (Exception E {if (log.iswarnenabled ()) {Log.warn ("Delete User:" + e.getmessage ());}}}}

The console output is as follows:

 INFO [spring.aop.aspect.serviceaspect:40] before execution (User Cn.ysh.studio.spring.aop.service.UserService.get ( Long) INFO [spring.aop.service.userservice:19] GetUser method ... INFO [spring.aop.aspect.serviceaspect:60] around execution (User cn.ysh.studio.spring.aop.service.UserService.get ( Long)) Use time:42 ms! INFO [spring.aop.aspect.serviceaspect:48] After execution (User cn.ysh.studio.spring.aop.service.UserService.get ( Long) INFO [spring.aop.aspect.serviceaspect:74] afterreturn Execution (User Cn.ysh.studio.spring.aop.service.UserService.get (Long) INFO [spring.aop.aspect.serviceaspect:40] before execution (void Cn.ysh.studio.spring.aop.service.UserService.save (User)) INFO [spring.aop.service.userservice:26] Saveuser method ... INFO [spring.aop.aspect.serviceaspect:60] around execution (void Cn.ysh.studio.spring.aop.service.UserService.save ( User)) Use Time:2 ms! INFO [spring.aop.aspect.serviceaspect:48] after execution (void Cn.ysh.studio.spring.aop.service.UserService.save ( UsER) INFO [spring.aop.aspect.serviceaspect:74] Afterreturn Execution (void Cn.ysh.studio.spring.aop.service.UserService.save (User) INFO [spring.aop.aspect.serviceaspect:40] Before Execution (Boolean cn.ysh.studio.spring.aop.service.UserService.delete (Long)) INFO [Spring.aop.service.UserService : +] Delete method ... INFO [spring.aop.aspect.serviceaspect:65] around execution (Boolean Cn.ysh.studio.spring.aop.service.UserService.delete (long)) use Time:5 ms with exception:spring AOP throwadvice demo INFO [ SPRING.AOP.ASPECT.SERVICEASPECT:48] After execution (Boolean cn.ysh.studio.spring.aop.service.UserService.delete ( Long) INFO [spring.aop.aspect.serviceaspect:74] Afterreturn Execution (Boolean Cn.ysh.studio.spring.aop.service.UserService.delete (long)) WARN [studio.spring.aop.tester:32] Delete user:null Return value from advice does not match primitive return type For:public boolean cn.ysh.studio.spring.aop.service.UserSer Vice.delete (long) throws Java.lang.Exception

You can see that, as we expected, although we did not make any changes to the Userserivce class including its invocation, spring still intercepts the invocation of the method, which is perhaps the magic of AOP.

The simple way to say the XML configuration is as simple as that:

<?xml version= "1.0" encoding= "UTF-8"? ><beans xmlns= "Http://www.springframework.org/schema/beans" xmlns: Xsi= "Http://www.w3.org/2001/XMLSchema-instance" xmlns:context= "Http://www.springframework.org/schema/context" xmlns:aop= "HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP" xsi:schemalocation= "Http://www.springframework.org/schema /AOP Http://www.springframework.org/schema/aop/spring-aop-3.1.xsdhttp://www.springframework.org/schema/beans Http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http ://www.springframework.org/schema/context/spring-context-3.0.xsd "><!--slice Bean--><bean id= for system service Components" Serviceaspect "class=" Cn.ysh.studio.spring.aop.aspect.ServiceAspect "/><!--AOP configuration--><aop:config> <!--declare a facet and inject a tangent bean, equivalent to @aspect--><aop:aspect id= "Simpleaspect" ref= "serviceaspect" ><!--Configure a pointcut, Equivalent to @pointcut--><aop:pointcut expression= "Execution (* cn.ysh.studio.spring.aop.service. *(..))" Id= "SimplepointCut "/><!--configuration notification equivalent to @before, @After, @AfterReturn, @Around, @AfterThrowing--><aop:before pointcut-ref=" Simplepointcut "method=" before "/><aop:after pointcut-ref=" Simplepointcut "method=" after "/&GT;&LT;AOP: After-returning pointcut-ref= "Simplepointcut" method= "Afterreturn"/><aop:after-throwing pointcut-ref= " Simplepointcut "method=" Afterthrow "throwing=" ex "/></aop:aspect></aop:config></beans>

You may disagree with the idea that the individual is not as flexible and powerful as the annotations, but you do not know if the following code will make your idea better:

Configure the pre-notification to intercept the return value of Cn.ysh.studio.spring.mvc.bean.User @before ("Execution (Cn.ysh.studio.spring.mvc.bean.User Cn.ysh.studio.spring.aop.service. *(..))") public void Beforereturnuser (Joinpoint joinpoint) {if (log.isinfoenabled ()) {Log.info ("Beforereturnuser" + JoinPoint);}} To configure a pre-notification, intercept the Cn.ysh.studio.spring.mvc.bean.User method @before ("Execution (* cn.ysh.studio.spring.aop.service. * (Cn.ysh.studio.spring.mvc.bean.User)) "public void Beforearguser (Joinpoint joinpoint) {if (log.isinfoenabled ()) { Log.info ("Beforearguser" + Joinpoint);}} Configure a pre-notification, intercept a method containing a long parameter, and inject the parameter value into the current method's formal parameter ID @before ("aspect () &&args (ID)") public void Beforeargid ( Joinpoint Joinpoint, long id) {if (log.isinfoenabled ()) {Log.info ("Beforeargid" + Joinpoint + "\tid:" + ID);}}

Attach UserService code (in fact very simple):

Package Cn.ysh.studio.spring.aop.service;import Org.apache.commons.logging.log;import Org.apache.commons.logging.logfactory;import cn.ysh.studio.spring.mvc.bean.user;/** * User Service Model * @author Shenghany * @  Date 2013-5-28 */public class UserService {Private final static log log = Logfactory.getlog (userservice.class);p ublic User Get (Long id) {if (log.isinfoenabled ()) {Log.info ("GetUser method ...");} return new User (); public void Save (user user) {if (log.isinfoenabled ()) {Log.info ("Saveuser method ...");}} Public Boolean delete (Long id) throws Exception{if (Log.isinfoenabled ()) {Log.info ("Delete method ..."); throw new Exception ("Spring AOP throwadvice Demo");} return false;}}

It should be said that learning Spring AOP has two difficulties, the 1th is to understand the concept of AOP and related concepts, the 2nd is to flexibly grasp and use pointcut expressions. The concept of understanding is usually not overnight, slowly soak for a long time, naturally understand, the following we briefly introduce the Pointcut expression configuration rules.

In general, the use of "execution" in an expression can satisfy most of the requirements. The expression format is as follows:

    • modifiers-pattern: Operation Permissions for methods
    • ret-type-pattern: return value
    • Declaring-type-pattern: The package where the method resides
    • Name-pattern: Method Name
    • parm-pattern: Name of parameter
    • Throws-pattern: Exception

Among them, other than Ret-type-pattern and Name-pattern, the others are optional. In the example above, execution (* com.spring.service.*.* (..)) Represents the Com.spring.service package, the return value is any type, the method name is arbitrary, the parameters are not limited to all methods.

Finally, let's talk about the notification parameters

Parameters can be bound by args so that the specific parameters can be accessed in the notification (Advice). For example, the,<aop:aspect> is configured as follows:

<aop:config>  <aop:aspect id= "Testaspect" ref= "Aspectbean" >   <aop:pointcut id= " Businessservice "    expression=" Execution (* com.spring.service.*.* (String,..)) and args (msg,..) "/>    < Aop:after pointcut-ref= "Businessservice" method= "Doafter"/>  </aop:aspect></aop:config>

The above code, args (msg,..) is to add the first string type parameter on the Pointcut method to the parameter named MSG, so that the parameter can be used directly.

Access the current connection point

As already seen in the aspect slice bean above, the first parameter of each notification method is joinpoint. In fact, in spring, any notification (Advice) method can define the first parameter as a org.aspectj.lang.JoinPoint type to accept the current connection point object. The Joinpoint interface provides a number of useful methods, such as Getargs () (Returning method parameters), Getthis () (Returning the proxy object), Gettarget () (returning to the target), Getsignature () (Returning information about the method being notified), and ToString () (prints out useful information about the method being notified).

Source: http://ntzrj513.blog.163.com/blog/static/27945612201362232315/

Appendix:

Interface Signature
All known subinterfaces:
advicesignature, Catchclausesignature, Codesignature, Constructorsignature, Fieldsignature, Initializersignature, Locksignature, Membersignature,methodsignature, Unlocksignature
All known implementing Classes:
Fieldsignatureimpl
Signature

Represents the signature at a join point. This interface parallels java.lang.reflect.Member .

This interface was typically used for tracing or logging applications to obtain reflective information about the join point , i.e. using the J2SE 1.4 java.util.logging API

Aspect Logging {     Logger Logger = Logger.getlogger ("methodentries");      Before (): Within (Com.bigboxco. *) && Execution (public * * (..)) {         Signature sig = Thisjoinpoint.getsignature ();         Logger.entering (Sig.getdeclaringtype (). GetName (),                         sig.getname ());     

More detailed information about a specific kind of signature can is obtained by casting this object to one of its Signature More specific sub-types available in org.aspectj.lang.reflect .

See Also:
Memberjava.util.logging.Logger
Getdeclaringtypename
Getdeclaringtypename ()
Returns The fully-qualified name of the declaring type. This is equivalent to calling Getdeclaringtype (). GetName (), but caches the result for greater efficiency.
GetName
GetName ()
Returns The identifier part of this
signature. For methods This would return the method name.

See Also:
Member.getName()

Source: http://www.eclipse.org/aspectj/doc/released/runtime-api/org/aspectj/lang/Signature.html

Annotation-based configuration and use of spring AOP-reproduced

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.