Annotation-based spring AOP configuration and usage

Source: Internet
Author: User
Tags first string getmessage modifiers

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:

  • pre-notification (before advice): A notification that is performed 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): A 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.

  • after return notification (after return advice): A notification that is executed after a connection point is completed normally, excluding the case of throwing an exception. The ApplicationContext uses <after-returning> elements to declare in <aop:aspect>.

  • Surround 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 exception exits. 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.

Note First, the use of annotations to configure Spring AOP is a two-step overall, the first step is to declare the activation of the auto-scan component function in the XML file, while activating the automatic proxy feature (and 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 components configured with 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 objects  --><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 facets bean *  @author  shenghany  *  @date  2013-5-28 *///Statement 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 (*&NBSP;CN.YSH.STUDIO.SPRing.aop.service. *(..))") Public void aspect () {}/* *  configures the pre-notification, using the pointcut that is registered on method aspect ()  *  accepts the Joinpoint Pointcut object at the same time, This parameter can be  */@Before ("aspect ()") Public void before (Joinpoint joinpoint) {if (log.isinfoenabled ( ) {Log.info ("before "  + joinpoint);}} Configure the post notification using the Pointcut @after ("aspect ()") registered on Method aspect () Public void after (joinpoint joinpoint) {if ( Log.isinfoenabled ()) {Log.info ("after "  + joinpoint);}} Configure the surround notification using the Pointcut @around ("aspect ()") registered on Method 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 +  "\tuse 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);}} 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&NBSP;AOP test  *  @author  Shenghany *  @date  2013-5-28 */public class  tester {private final static log log = logfactory.getlog (Tester.class );p Ublic static void main (String[] args)  {//start the spring container applicationcontext context  = new classpathxmlapplicationcontext ("Applicationcontext.xml");//Get Service Components userservice  service =  (UserService)  context.getbean ("UserService");//three methods of calling UserService objects in a normal way 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:32] 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]& nbSp;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.UserService.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 "><!--  facets bean --><bean id=" serviceaspect "for system services components  class= "Cn.ysh.studio.spring.aop.aspect.ServiceAspect"/><!--&NBSP;AOP configuration  --><aop:config ><!--  declares a facet and injects a slice 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 notifications, equivalent to @before, @After, @AfterReturn, @Around, @AfterThrowing  -- ><aop:before pointcut-ref= "Simplepointcut"  method= "before"/><aop:after pointcut-ref = "Simplepointcut"  method= "after"/><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:

Execution (Modifiers-pattern ret-type-pattern declaring-type-pattern? Name-pattern (Param-pattern) Throws-pattern?)

    • 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" express ion= "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

public interface

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:

    • Member,java.util.logging.Logger

Getdeclaringtypename
Java.lang.String ()
    • Returns the fully-qualified name of the declaring type. This is equivalent to calling Getdeclaringtype (). GetName (), but caches the result for greater efficiency.

GetName
Java.lang.String ()
    • Returns The identifier part of this signature. For methods This would return the method name.

      • See Also:

      • Member.getName()

Annotation-based spring AOP configuration and usage

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.