Use spring for aspect Programming

Source: Internet
Author: User

 

Use spring for aspect Programming

I. AOP Theory

AOP is short for Aspect Oriented Programming, meaning: Aspect-oriented programming (also called Aspect-Oriented ), the pre-compilation method and runtime dynamic proxy can be used to dynamically and uniformly add functions to the program without modifying the source code. AOP can be used to isolate all parts of the business logic, thus reducing the Coupling Degree between each part of the business logic, improving the reusability of the program, and improving the development efficiency.

UCross-cutting concerns

These concerns are called cross-section concerns.

UAspect (slice)

It refers to the abstract of the cross-cutting concerns, that is, the abstract of the object features, and the abstract of the cross-cutting concerns.

UJoinpoint)

The so-called connection points are the intercepted points (that is, the methods of classes to be intercepted ). In spring, These vertices can only be methods, because spring only supports method interception. In fact, joinpoint can also intercept field or class constructor.

UPointcut)

The so-called entry point refers to the definitions of intercept a jointpoint, that is, the methods defined in the section, and declares that the method intercepts a jointpoint ).

UAdvice (notification)

The so-called notification refers to the things to be done after the entry point intercepts the jointpoint (connection point. Notifications can be divided into pre-notification (@ before), post-notification (@ afterreturning), exception notification (@ afterthrowing), final notification (@ After), and surround notification (@ around ).

UTarget)

The target object of the proxy.

UWeave (woven)

The process of applying aspects to the target object and causing proxy object creation is called weaving.

UIntroduction (introduced)

Without modifying the class code, introduction can dynamically add some methods or fields to the class at runtime ).

Ii. AOP Programming Method

To use AOP for programming, we need to first introduce the AOP namespace in the spring configuration file (for example, applicationcontext. XML). The content of the configuration file is shown in the red font below:

<BeansXmlns= "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/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

Http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd

Http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd ">

Spring provides two kinds of AOP programming methods. We can choose either of them for AOP programming.

1. annotation-based AOP Programming

2. AOP Programming Based on XML Configuration

Iii. demo of AOP Programming

Here, we demonstrate aspectbean section to intercept studentmgr's update method (connection point) to describe how aspect programming works. The xml configuration information is provided later.

1. Build an AOP programming environment

References for building the AOP Environment
Build a spring development environment using Maven.

2. Enable Annotation

Add the following bean to the spring configuration file to enable spring annotation programming.

<Bean class = "org. springframework. AOP. aspectj. annotation. annotationawareaspectjautoproxycreator"/>

 

3. Define the istudentmgr interface and Bean class studentmgr. The Code is as follows:

IstudentmgrInterface Java code:

package com.trs.components.mgr; public interface IStudentMgr {    public void save(String _sStudentName) throws Exception;    public void update(String _sStudentName) throws Exception;} 

StudentmgrBean Java code:

Package COM. TRS. components. mgr; public class studentmgr implements istudentmgr {public void save (string _ sstudentname) throws exception {system. out. println ("saves the student object .. ");} public void Update (string _ sstudentname) throws exception {system. out. println ("updated student object .. ");}}

 

4. Write the partition class aspectbean. The Code is as follows:

Package COM. TRS. components. AOP; import Org. aspectj. lang. joinpoint; import Org. aspectj. lang. proceedingjoinpoint; import Org. aspectj. lang. annotation. after; import Org. aspectj. lang. annotation. afterthrowing; import Org. aspectj. lang. annotation. around; import Org. aspectj. lang. annotation. aspect; import Org. aspectj. lang. annotation. before;/*** intercept the aspect of studentmgr ***/@ aspect // declare a public class aspectbean {@ befor E ("execution (* COM. TRS. components. mgr. studentmgr. update *(..)) ") // declare the pre-notification and intercept all methods of studentmgr starting with update public void validateuser (joinpoint pjp) throws throwable {system. out. println ("Perform user verification! ");} @ Before (" execution (* COM. TRS. components. mgr. studentmgr. update *(..)) ") // declare the pre-notification and intercept all methods of studentmgr starting with update public void begintransaction (joinpoint _ JP) throws throwable {// if you need to process the parameters passed in at the connection point, you can use the code to obtain: _ JP. getargs (); system. out. println ("START transaction");} @ After ("execution (* COM. TRS. components. mgr. studentmgr. update *(..)) ") // declare the final notification to intercept all methods of studentmgr starting with update public void endtransaction () throws throwable {system. out. println ("End transaction") ;}@ after ("execution (* COM. TRS. components. mgr. studentmgr. update *(..)) ") // declare the final notification and intercept all methods of studentmgr starting with update public void writeloginfo () {system. out. println ("logging log information");} @ afterthrowing (pointcut = "execution (* COM. TRS. components. mgr. studentmgr. update *(..)) ", throwing =" ex ") // declaration exception. When the update method of the studentmgr class encounters an exception, execute public void printexception (exception ex) {system. out. println ("an error occurred when executing the update method" + ex. getmessage ();} @ around ("execution (* COM. TRS. components. mgr. studentmgr. update *(..)) ") // declare the surround notification to intercept all methods of studentmgr starting with update public object dosurround (proceedingjoinpoint _ pjp) throws throwable {// if you need to process the parameters passed in at the connection point, you can get it by code: pjp. getargs (); object result; If (true) {// you can determine whether to enter this if System Based on the conditions. out. println ("Enter the surround notification... "); Result = _ pjp. proceed (); // This method must be executed when surround notification is used; otherwise, the intercepted method will no longer execute system. out. println ("Exit surround notification... ");} // return the returned value after execution: return result ;}}

 

Note:

[1] @ before ("execution (* COM. TRS. components. mgr. studentmgr. update *(..)) ") the first" * "indicates that the return value of the matching method can be of any type. The second" * "indicates that all methods starting with update will be blocked ;(..) it indicates that the input parameters of these methods can be 0 or multiple.

[2] The throwing = "ex" in @ afterthrowing indicates that an exception named ex is returned when a method error occurs. You can obtain the error object through the ex parameter in the start point.

[3] note the writing of the surround method dosurround

L The first parameter type in the wrap method must be the proceedingjoinpoint type (the wrap method name can be called at will ).

L throwable type when exceptions thrown by the surround method are required

L The _ pjp. Proceed () method must be executed in the surround method. Otherwise, the intercepted method will not be executed.

L add a time point before and after the _ pjp. Proceed () method to test the execution time of the intercepted method.

5. Some bean configurations of the partition class

Add the following code to the spring configuration file to configure the Bean class.

<? 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/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

Http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd

Http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd ">

 

<Bean class = "org. springframework. AOP. aspectj. annotation. annotationawareaspectjautoproxycreator"/>

<Bean id = "aspectbean" class = "com. TRS. components. AOP. aspectbean"> </bean>

<Bean id = "istudentmgr" class = "com. TRS. components. Mgr. studentmgr"> </bean>

</Beans>

6. Write Test Cases

Use JUnit to write a test case for testing the studentmgr. Update method. The code for the test case is as follows:

@ Test

Public voidTestupdate ()ThrowsException {

// Use applicationcontext to initialize the system

Applicationcontext context =NewClasspathxmlapplicationcontext (

"Applicationcontext. xml ");

Istudentmgr studentmgr = (istudentmgr) Context. getbean ("istudentmgr ");

// Studentmgr. saveone ("Wuguowei");

System.Out. Println ("-----------");

Studentmgr. Update ("wuguowei ");

}

7. Execute test cases and view the printed results

Start transaction

Perform user verification!

Enter the surround notification...

Updated student object ..

End transaction

Record log information

Exit the surround notification...

8. AOP programming for the xml configuration corresponding to the instance

The above is the annotation-style AOP programming. The above example programming can also adopt the xml configuration method of AOP programming, you only need to add the following code to the spring configuration file (for the xml configuration of AOP, see the red section below ):

<? 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/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

Http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd

Http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd ">

<AOP: config>

<AOP: aspect id = "asp_bean_id" ref = "aspectbean">

<AOP: pointcut id = "mypointcut" expression = "execution (* COM. TRS. components. Mgr. studentmgr. Update * (...)"/>

<AOP: Before pointcut-ref = "mypointcut" method = "validateuser"/>

<AOP: Before pointcut-ref = "mypointcut" method = "begintransaction"/>

<AOP: After pointcut-ref = "mypointcut" method = "endtransaction"/>

<AOP: After pointcut-ref = "mypointcut" method = "writeloginfo"/>

<AOP: After-throwing pointcut-ref = "mypointcut" method = "printexception"/>

<AOP: Around pointcut-ref = "mypointcut" method = "dosurround"/>

</AOP: aspect>

</AOP: config>

 

<Bean class = "org. springframework. AOP. aspectj. annotation. annotationawareaspectjautoproxycreator"/>

<Bean id = "anotheraspect" class = "com. TRS. components. AOP. anotheraspect"> </bean>

<Bean id = "aspectbean" class = "com. TRS. components. AOP. aspectbean"> </bean>

<Bean id = "istudentmgr" class = "com. TRS. components. Mgr. studentmgr"> </bean>

</Beans>

 

Iv. FAQs

1. How can I determine the execution sequence of notifications in the same aspect?

If you want to run multiple notifications in the same plane at the same connection point, the execution sequence of these notifications is unknown (the reason for the query is that there is no way to obtain the Declaration sequence of methods by reflecting the classes generated by javac ). If this happens, we need to compress these methods into a notification, or abstract these methods into different slices, and specify the execution order by the plane priority.

2. How can I determine the order of the notifications in different slices?

The order of the notifications in different slices is determined based on the priority of the slice. We need to implement "Org. springframework. core. ordered interface, through the getorder () method of the implementation interface to determine the priority, the smaller the number returned, the higher the priority, the higher the priority, the notification in the aspect is executed first. For pre-notifications, the higher the priority, the higher the priority. For post-notifications, the higher the priority, the later the execution.

3. Will new instances trigger notifications?

The instance generated by using the new method does not trigger the aspect notification. For example, in the above instance, the following code calls the update method will not trigger the notification.

Studentmgr astudentmgr = new studentmgr ();

Astudentmgr. Update ("wuguowei"); // The new instance object does not trigger the aspect notification.

4. Can the bean obtained by applicationcontext be an interface?

When we obtain bean through spring applicationcontext, the returned object can be an interface or interface implementation. If an implementation class inherits the interface, however, if you convert the obtained class to an implementation class, an error is returned. For example, execute the following code:

Applicationcontext context =NewClasspathxmlapplicationcontext ("applicationcontext. xml ");

Studentmgr = (studentmgr) Context. getbean ("istudentmgr"); // an error is reported here. studentmgr implements the interface. If it is converted to an interface, no error is reported.

The following conversion error is reported. The information is as follows:

Java. Lang. classcastexception: $ proxy9 cannot be cast to com. TRS. components. Mgr. studentmgr

At com. TRS. components. Mgr. studentmgrtest. testupdate (studentmgrtest. Java: 29)

At sun. Reflect. nativemethodaccessorimpl. invoke0 (native method)

At sun. Reflect. nativemethodaccessorimpl. Invoke (nativemethodaccessorimpl. Java: 57)

At sun. Reflect. delegatingmethodaccessorimpl. Invoke (delegatingmethodaccessorimpl. Java: 43)

5. Differences between beanfactory and applicationcontext

L beanfactory is mainly responsible for configuring and managing Bean objects and loading them.

L applicationcontext is an extension class of beanfactory. It includes all the features of beanfactory and adds more features that support enterprise core content, such as AOP.

L beanfactory is delayed loading, and applicationcontext loads all beans during initialization. In this way, applicationcontext can detect bugs in the program earlier, while beanfactory can only detect bugs in the program when it is used.

6. Description of the entry point expression

In Spring AOP, we often use execution pointcut designator to define the entry point. The expression format is as follows:

Execution (modifiers-pattern? Ret-type-pattern declaring-type-pattern? Name-pattern (param-pattern) throws-pattern ?)

Except for the return type mode (ret-type-pattern in the code snippet above), the name mode and parameter mode are all optional. The return type mode determines that the return type of the method must match a connection point in sequence. The most frequent return type pattern you will use is *, which indicates matching any return type. Only the methods of the given type are returned. The name pattern matches the method name. You can use the * wildcard as the all or part of the naming mode. The parameter mode is a little complicated: () matches a method that does not accept any parameters, and (...) matches a method that accepts any number of parameters (zero or more ). Mode (*)
Matches a method that accepts any type of parameter. The mode (*, string) matches a method that accepts two parameters. The first method can be of any type, and the second method must be of the string type. See the language semantics section in the aspectj programming guide.

UExecution of any public Method:

Execution (Public **(..))

UExecution of any method starting with "set":

Execution (* Set *(..))

UExecute any methods of the accountservice Interface:

Execution (* COM. XYZ. Service. accountservice .*(..))

UDefine execution of any method in the service package:

Execution (* COM. XYZ. Service .*.*(..))

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.