The Spring Series AOP

Source: Internet
Author: User
Tags throwable

First, what is AOP
AOP (aspect-orientedprogramming, aspect-oriented programming) can be said to complement and improve OOP (object-oriented programing, object-oriented programming). OOP introduces concepts such as encapsulation, inheritance, and polymorphism to create an object hierarchy that simulates a collection of public behavior. When we need to introduce public behavior to scattered objects, oop seems powerless. In other words, OOP allows you to define relationships from top to bottom, but it is not appropriate to define left-to-right relationships. such as logging capabilities. Log code is often spread horizontally across all object hierarchies, and has nothing to do with the core functionality of the objects it spreads to. This is true for other types of code, such as security, exception handling, and transparent persistence. This irrelevant code scattered around is called crosscutting (cross-cutting) code, and in OOP design, it leads to a lot of duplication of code, rather than the reuse of individual modules.

AOP, on the contrary, uses a technique called "crosscutting" that splits the encapsulated object interior and encapsulates public behavior that affects multiple classes into a reusable module, called "Aspect", which is the facet. The so-called "aspect", in a nutshell, is to encapsulate the logic or responsibility that is not related to the business, but for the common invocation of the business module, to reduce the duplication of code in the system, to reduce the coupling between modules, and to facilitate future operability and maintainability. AOP represents a horizontal relationship, if the "object" is a hollow cylinder, which encapsulates the properties and behavior of the object, then the aspect-oriented programming approach is like a razor that cuts through the hollow cylinders to get inside the message. The cut-off aspect is the so-called "facet". Then it hands the cut-off slices with a clever capture of the heavens, leaving no traces.

Using "crosscutting" techniques, AOP divides software systems into two parts: core concerns and crosscutting concerns. The main process of business process is the core concern, and the part that has little relation is the crosscutting concern. One feature of crosscutting concerns is that they often occur in many of the core concerns and are essentially similar everywhere. such as permission authentication, logging, transaction processing. The role of AOP is to separate the various concerns in the system, separating the core concerns from the crosscutting concerns. As Avanade's senior program architect Adam Magee says, the core idea of AOP is "separating the business logic in the application from the generic services that support it." ”

The implementation of AOP technology, mainly divided into two categories: first, the use of dynamic Agent technology, the use of interception of messages to decorate the message to replace the original object behavior, the second is the use of static weaving, the introduction of a specific syntax to create "aspects", so that the compiler can be woven into the relevant "aspects" The code.

Ii. AOP Usage Scenarios
AOP is used to encapsulate crosscutting concerns, which can be used in the following scenarios:
Authentication Permissions
Caching Cache
Context Passing content delivery
Error handling Errors Handling
Lazy Loading lazily loaded
Debugging commissioning
Logging, tracing, profiling and monitoring record tracking optimization calibration
Performance Optimization Performance optimization
Persistence persistence
Resource Pooling resource Pool
Synchronization synchronization
Transactions transactions

Iii. AOP-related concepts

1. Connection point (Joinpoint)
A particular location where the program executes: Before the class begins to initialize, after the class is initialized, before a method call to a class, after a call, etc., a class or program code has some specific points with a boundary nature, and the specific points in the code become "connection points," and spring supports only the connection points of the methods. That is, you can only perform point weaving enhancements before the method call, after the method call, and before and after the method call. For example, the hacker attack system needs to find a breakthrough, there is no way to attack without a breakthrough, in a way, AOP is a hacker, the connection point is an AOP to target class attack candidate points.

The connection point has two information to determine: The first is the program execution point represented by the method, and the second is the azimuth represented by the relative point, such as the connection point before the Test.foo () method is executed, the execution point is Test.foo, and the azimuth is the position before the method executes. Spring uses pointcuts to position the execution point, while the bearing is defined in the enhanced type.

2. Pointcut (Pointcut)
Each program class has many connection points, such as a class with two methods, both of which are connection points, that is, the connection point is an objective object in the program class. But how do you navigate to a connection point in a large number of connection points? AOP locates specific connection points by tangency. Understanding Pointcuts and connection points through the concept of database queries: Connection points are equivalent to records in a database table, and tangency is equivalent to a query condition. Connection points and pointcuts are not one by one corresponding relationships, and a pointcut can match multiple connection points.

In spring, the pointcut is described by the Org.springframework.aop.Pointcut interface, which uses classes and methods as the query criteria for the connection point, and the rules parsing engine of spring AOP is responsible for parsing the query conditions set by the pointcut and finding the corresponding connection points , in fact, it should be the execution point rather than the connection point, because the connection point is the method before execution, after execution and so on, including bearing information of the specific program execution point, and the tangent only to a method, so if you want to locate the specific connection point, you also need to provide orientation information.

3. Enhancement (Advice)
Enhancement is a piece of program code that is woven into the target class connection point (like AOP loading a trojan into a business class as a hacker), and the enhancement also has a connection-point-related information, which is the orientation of the execution point. Combining the execution point azimuth information and the pointcut information, we can find a specific connection point, so spring provides the enhanced interface is with the bearing name: Befortadvice, Afterreturningadvice, Throwsadvice and so on. (Some translate advice into a notification, but the notification is to communicate a message to the notified person, and does not do anything for the notified person, and spring's advice must be embedded in a class connection point, and completed an additional application logic;)

4. Destination object (target)
To enhance the logical weaving target class, if there is no AOP, the target business class needs to implement all of its own logic, with the help of AOP, the target class only implements those non-crosscutting logic of the program logic, while other monitoring code can use AOP to dynamically weave into the specific connection point.

5. Introduction (Introduction)
Introduction is a special enhancement, it adds some properties and methods for the class, so that even if a business class originally did not implement an interface, through the introduction of AOP, we can dynamically add the implementation logic of the interface for the business class, so that the business class becomes the implementation of this interface class.

6. Weave in (Weaving)
Weaving is the process of adding enhancements to the specific connection point of the target class, and AOP is like a loom that weaves target classes, enhancements, or primers together, and AOP has three ways to weave it in:
A. Weaving during compilation, which requires the use of a special Java compiler;
B. class loading period weaving, which requires the use of special class loaders;
C. Dynamic agent weaving, adding a way to enhance the generation of subclasses for the target class at run time.
Spring uses dynamic proxy weaving, while the ASPECTJ is woven into the compiler and class loading stages.

7. Agent (proxy)
Once a class is augmented by AOP, it produces a result class, which is a proxy class that incorporates both the original class and the enhanced logic.

8. Facets (Aspect)
Facets consist of tangency and enhancement, which includes both the definition of crosscutting logic and the definition of connection points, and Spring AOP is the framework responsible for implementing facets that weave the crosscutting logic defined by the facets into the connection points specified by the facets.

Summary: The focus of AOP is on how to apply the enhancement to the target object's connection point, which first includes two jobs: first, how to navigate to the connection point through tangency and enhancement, and second, how to write the section code in the enhancement.

Iv. Principle of realization

1. Proxy mode

The concept of an agent: a simple understanding is that by creating a proxy object for an object, we do not directly reference the original object, but rather the proxy object created to control the reference to the original object.

Proxy mode is a common Java design pattern, his characteristic is that the proxy class and the delegate class (or target Class) have the same interface, the proxy class is mainly responsible for the delegate class preprocessing messages, filtering messages, forwarding messages to the delegate class, and post-processing messages. There is usually an association between the proxy class and the delegate class, and the object of a proxy class is associated with an object of a delegate class, and the object of the proxy class does not actually implement the service, but instead provides a specific service by invoking the related method of the object of the delegate class.
The proxy class can be divided into two types according to the agent's creation period.
static Proxy: The source code is generated automatically by the programmer or a specific tool, and then compiled. Before the program runs, the. class file for the proxy classes already exists.
Dynamic Proxy: when the program is running, it is created dynamically using the reflection mechanism, without having to write code manually. Dynamic proxies not only simplify programming, but also improve the scalability of software systems, because the Java reflection mechanism can generate any type of dynamic proxy class.

Agent principle: The proxy object contains a reference to the real object, so that the real object can be manipulated, while the proxy object provides the same interface as the real object to replace the real object at any moment. At the same time, the proxy object can attach other actions when performing the real object operation, which is equivalent to encapsulating the real object.

The implementation principle of 2.AOP

The key to AOP implementation is the AOP proxy, which is automatically created by the AOP framework. AOP proxies are divided into two main categories:
. Static proxies: Compile using the commands provided by the AOP framework to generate an AOP proxy class at compile time, which is also known as compile-time enhancement; a static proxy is represented by a aspectj.
Dynamic proxies: With the help of JDK dynamic proxies at runtime, Cglib, etc., are temporarily generating AOP dynamic proxy classes in memory, and therefore also known as runtime enhancements, and Spring AOP uses dynamic proxies.

AOP is divided into static AOP and dynamic AOP. Static AOP refers to the AOP implemented by ASPECTJ, which compiles the slice code directly into a Java class file. Dynamic AOP refers to the AOP that dynamically weaves the slice code into implementation. Spring's AOP is Dynamic AOP, which is implemented by the dynamic agent technology and CGLIB (Dynamic bytecode enhancement technology)provided by the JDK . Although the implementation technique is different, it is based on the proxy pattern, which is the generation of a proxy object.

(1) JDK dynamic agent

A. The JDK dynamic agent is interface-oriented and must provide an interface to be implemented by both the delegate class and the proxy class, and only the methods in the interface can be proxied.
B. The implementation of the JDK dynamic agent mainly uses the proxy class and the Invocationhandler interface in the Java.lang.reflect package.

Invocationhandler Interface:

Let's take a look at how the Java API Help document describes the Invocationhandler interface:


Dispatched to the Invoke method of its invocation handler.

Note: Each dynamic proxy class must implement the Invocationhandler interface, and each instance of the proxy class is associated to a handler, when we call a method through the proxy object, The invocation of this method is forwarded to the Invoke method of this interface by Invocationhandler. At the same time, in the Invoke method we can enhance the method call of the proxy object (such as adding transaction, log, permission authentication and so on). Let's take a look at the only way to invocationhandler this interface. The Invoke method:

Public interface Invocationhandler {public      object Invoke (Object Proxy,method method,object[] args) throws Throwable ; }

Parameter description:
Object proxy: Refers to the objects being proxied.
Methods: The method to invoke. (Refers to the method object that we are going to invoke the proxy object for.)
Object[] args: The arguments that are required when the method is called. (refers to a parameter that is accepted when a method of a real object is called)

The subclass of the Invocationhandler interface can be imagined as a proxy's final operation class, replacing the Proxysubject.

Proxy class:
The proxy class is an action class that specifically completes the proxy, which can be used to dynamically generate an implementation class for one or more interfaces, which provides the following operations:

Parameter description:
ClassLoader Loader: Class loader
Class<?>[] Interfaces: Get all the interfaces
Invocationhandler h: Get subclass instance of Invocationhandler interface

Example of a JDK dynamic proxy:

Define a business interface Iuserservice, as follows:

Package Com.spring.aop;public interface Iuserservice {    //Add user public    void AddUser ();    Delete user public    void DeleteUser ();}

A simple implementation of the class Userserviceimpl, as follows:

Package Com.spring.aop;public class Userserviceimpl implements iuserservice{public        void AddUser () {        System.out.println ("A new user! ");    }        public void DeleteUser () {        System.out.println ("deleted a user! ");    }}

What we are going to do now is to dynamically implant the process before and after AddUser and DeleteUser.
The JDK dynamic agent uses two classes in the Java.lang.reflect package: Proxy and Invocationhandler.
Invocationhandler is an interface that dynamically weaves cross-cutting logic and business logic together by implementing the interface to define crosscutting logic and invoking the code of the target class through a reflection mechanism.
Proxy uses Invocationhandler to dynamically create an instance that conforms to an interface, generating a proxy object for the target class.
As below, we create a Invocationhandler instance Dynamicproxy:(when executing the target method in the dynamic proxy object, actually replacing the Invoke method that calls Dynamicproxy)

Package Com.spring.aop;import Java.lang.reflect.invocationhandler;import Java.lang.reflect.method;public class Dynamicproxy implements invocationhandler{        //proxy object (that is, to create a proxy object for this target class)    private object target;        An instance of the delivery agent target, because the proxy processor is required, or it can be set, and so on. Public    Dynamicproxy (Object target) {        this.target=target;    }        /**     * Covers Java.lang.reflect.InvocationHandler method invoke () for weaving (enhancement) operations.     * This method is called to the proxy object, note that the internal method call object is the target object, can not write wrong.     * Parameter Description:     * Proxy is the generated proxy object, method is the proxy approach, args is the method to receive the parameter     *    /public object Invoke (object proxy, method method, object[] args) throws throwable{        //target methods before executing        System.out.println ("Do sth before ...");        The target class method is invoked through the reflection mechanism        Object result = Method.invoke (target, args);        After the target method executes        the SYSTEM.OUT.PRINTLN ("Do sth after...\n");        return result;}    }

Here is the test:

Package com.spring.aop;//method of creating a dynamic instance with the Java.lang.reflect.Proxy.newProxyInstance () method to invoke the proxy instance import Java.lang.reflect.proxy;public class Dynamictest {public        static void Main (string[] args) {        //Target business class        to be proxied Iuserservice target = new Userserviceimpl ();        Weave the target class and the Crosscutting class together        dynamicproxy handler= new Dynamicproxy (target);        Creates a proxy instance, which can be thought of as a subclass of the target business class to be proxied (method), or        create a proxy instance (using the proxy class and the custom invocation processing logic (handler) to generate a proxy object)        Iuserservice Proxy = (iuserservice) proxy.newproxyinstance (                target.getclass (). getClassLoader (),//class loader                for Target class Target.getclass (). Getinterfaces (),//interface of the target class                handler); Cross-cutting class        proxy.adduser ();        Proxy.deleteuser ();    }}

Description: The code above completes the work of the Business class code and the Crosscutting code, and generates the proxy instance, the first parameter of the Newproxyinstance method is the class loader, the second parameter is a set of interfaces implemented by the target class, and the third parameter is the braiding object that consolidates the business logic and the crosscutting logic.

Each call to a dynamic proxy instance is invoked through the handler (call processor) of the Invocationhandler interface, and the dynamic agent does nothing, but associates the interface and handler to be implemented when creating the dynamic agent. The dynamic agent to help the agent perform the task, to be forwarded to the handler to execute. It's actually called the Invoke method. (You can see that execution of the AddUser () and DeleteUser () methods of the agent instance is the Dynamicproxy invoke () method.) )

Operation Result:

Basic flow: Use the proxy class to create a dynamic proxy for the target class, and create an object of the callback class that implements the Invocationhandler interface, which has an invoke () in the callback class to intercept calls to the various methods of the target class. After you create the proxy, you can invoke the various methods of the target object directly on the proxy.

To implement dynamic agent steps:
A. To create a class that implements the interface Invocationhandler, he must implement the Invoke method.
B Create the class that is being proxied and the interface.
C Create a proxy by using the static method of proxy newproxyinstance (ClassLoader loader, class<?>[]interfaces, Invocationhandler handler).
D The method is called through the proxy.

there is a big limitation to using the JDK dynamic proxy, which is that it requires the target class to implement the interface of the corresponding method, which can only create proxy instances for the interface. as we can see in the Newproxyinstance method of the proxy in the test class above, the second parameter of the method is the interface of the target class. If the class does not implement an interface, it depends on the cglib dynamic proxy.

(2) Cglib dynamic Agent

Cglib uses very low-level bytecode technology to create a subclass for a class, and uses method interception techniques in subclasses to intercept calls to all of the parent methods and to seed the crosscutting logic.

Bytecode generation technology implementation of AOP, in fact, is to inherit the proxy object, and then override the method that needs to be proxied, when overwriting the method, it is natural to insert our own code. Because of the need to override the methods of the Proxied object, when using Cglib technology to implement AOP, it is necessary to require that the method that needs to be proxied cannot be the final method, because the final method cannot be overridden by the quilt class.

A. Using the Cglib dynamic Proxy does not require an interface, the generated proxy object is a subclass object of the target object, so the method that requires the proxy cannot be private or final or static.
B. Using the Cglib dynamic agent requires a jar-pack dependency on Cglib (import Asm.jar and Cglib-nodep-2.1_3.jar)

Cglibproxy is basically similar to the proxy mechanism of jdkproxy, except that the proxy object of its dynamic agent is not an implementation of an interface, but a subclass of the target class extension. In other words, JDKPROXY returns the dynamic proxy class, which is another implementation version of the interface implemented by the target class, which implements the proxy for the target class (as is the relationship between Userdaoproxy and Userdaoimp), and the dynamic proxy class returned by Cglibproxy. is a subclass of the Target proxy class (the proxy class extends the Userdaoimpl Class)

Cglib Agent Features:
CGLIB is the implementation of a proxy for a class, the principle of which is to generate a subclass of the specified target class and overwrite the method. Because inheritance is used, you cannot inherit from the Finall class .

We use Cglib to implement the above example:

The final action class for the agent:

Package Com.spring.aop;import Java.lang.reflect.method;import Net.sf.cglib.proxy.enhancer;import Net.sf.cglib.proxy.methodinterceptor;import Net.sf.cglib.proxy.methodproxy;public class CglibProxy implements        methodinterceptor{//enhancer, Dynamic code generator Enhancer enhancer = new enhancer (); /** * Create proxy Object * @param clazz * @return Returns the proxy object */public object GetProxy (class Clazz) {//sets the parent class, which is        proxy class (target Class) Enhancer.setsuperclass (Clazz);        Sets the callback (callback This.intercept ()) Enhancer.setcallback (this) when calling the parent class method;    Dynamic creation of subclass instances via bytecode technology (dynamically extending the Userserviceimpl Class) return Enhancer.create ();     }/** * Interception method: Intercepting and processing the call of the target method on the proxy instance, returning the result * obj: instance of the target object agent;     * Method: The target object invokes the method instance of the parent class;     * Args: Call the parent class method to pass the parameter; * Proxy: Agent method to call the target method */public object Intercept (object Obj,method method,object[] args,methodproxy proxy) t        Hrows throwable{System.out.println ("--------test the meaning of the four parameters of the Intercept method-----------"); System.out.println ("Obj: "+obj.getclass ());        System.out.println ("Method:" +method.getname ());        System.out.println ("Proxy:" +proxy.getsupername ()); if (args!=null&&args.length>0) {for (Object Value:args) {System.out.println ("args:" +v            Alue);        }}//target method before executing System.out.println ("Do sth before ...");        The target method invocation//method of calling the parent class through the proxy class instance, that is, the calling of the target business class method Object result = Proxy.invokesuper (obj, args);        After the target method executes the SYSTEM.OUT.PRINTLN ("Do sth after...\n");    return result; }}

Test class:

Package Com.spring.aop;public class Cglibproxytest {public        static void Main (string[] args) {        cglibproxy proxy= New Cglibproxy ();        The subclass of the target business class is generated dynamically by Java.lang.reflect.Proxy's GetProxy (), which is the proxy class, and then the proxy instance is        created by creating the proxy class by dynamically generating subclasses        Iuserservice target= (Iuserservice) proxy.getproxy (userserviceimpl.class);        Target.adduser ();        Target.deleteuser ();    }}

Basic flow: You need to write your own proxy class, it implements the Methodinterceptor interface, there is a intercept () callback method to intercept the call to the target method, which uses Methodproxy to invoke the target method. To create a proxy object, use the enhance class, which sets the target class of the proxy, the proxy class instance that is invoked by The Intercept () callback, and finally creates and returns the proxy instance with create ().

Output:

We see that the same effect is achieved. Its principle is to generate a subclass enhancer.create () of the parent class Enhancer.setsuperclass (Clazz), and then intercept the methods of the parent class Enhancer.setcallback (this). The method of the parent class is overwritten, so the parent class method cannot be final.

Summary:
(1). As you can see from the output, the final call is the subclass of Com.spring.aop.UserServiceImpl (also the proxy class) com.spring.aop.userserviceimpl$ $EnhancerByCGLIB $$ 43831205 of the methods.
(2). Private,final and static modified methods cannot be proxied.

Attention:
(1). Cglib is implemented by implementing a subclass of the target class to implement the proxy, without having to define the interface.
(2). The build proxy object uses most of the enhancer and inherits the Methodinterceptor interface of the callback interface to generate the proxy object. The purpose of setting the callback object is to be handled by the callback object when the proxy object method is invoked.
(3). Create subclass object is by using Enhancer class object, by setting Enhancer.setsuperclass (class Class) and Enhancer.setcallback (Callback Callback) To create a proxy object.

Explains the Intercept method for the Methodinterceptor interface:

Object Intercept (Object var1, Method var2, object[] var3, Methodproxy var4) throws Throwable;

Parameter description: The object var1 represents the subclass proxy object, Method Var2 represents the methods to be called reflection object, the third parameter is passed to the calling method parameters, The first three parameters and the Invocationhandler interface of the JDK invoke method parameter meaning is the same, the fourth parameter Methodproxy object is cglib generated to replace the method object, Using this object is more efficient than the JDK method object.

If you use the method object to invoke the methods of the target object: Method.invoke (var1, VAR3), you will fall into an infinite recursive loop because the target object at this time is the child proxy class object of the target class.

The Methodproxy class provides two invoke methods:

public object Invokesuper (Object obj, object[] args) throws Throwable;public object Invoke (Object obj, object[] args) thro WS Throwable;

Note that you should use the Invokesuper () method at this point, called by the name of the parent class method, if you use the Invoke method, you need to provide a target class object, but we only target class subclass proxy object, so we will fall into an infinite recursive loop.

The performance of dynamic proxy objects created by Cglib is much higher than the dynamic proxy objects created by the JDK, but it takes longer to create dynamic proxy objects than the JDK creates dynamic proxy objects.

Summary of JDK Agents and cglib agents (the prerequisite for generating proxy objects is AOP cut-in)
(1) If the target object implements an interface, AOP is implemented by default with the JDK's dynamic proxy. If you are simply using IOC to generate an object, and no AOP cut-in will not generate proxies, only new one instance to the Spring bean factory.
(2), if the target object implements an interface, you can force the use of Cglib to implement AOP
How to force AOP to be implemented using Cglib
* Add Cglib Library
* Add <aop:aspectj-autoproxy proxy-target-class= "true"/> in spring Config file to force the use of
(3), if the target object has not implemented the interface, must adopt the Cglib library, spring will automatically switch between the JDK dynamic agent and Cglib (without implementing the interface with the Cglib proxy, the class using the interface with the JDK dynamic proxy)

The difference between JDK dynamic agent and Cglib bytecode generation:
(1), theJDK dynamic agent can only be used to implement the interface of the class generation agent, and not for the class. Cglib is the implementation of a proxy for a class, mainly to generate a subclass of the specified class, overriding the methods in it. Because it is inheritance, it is best not to declare the class or method as final.
(2), JDK Agent is not required to rely on third-party libraries, as long as the JDK environment can be agent, it has several requirements
* Realization of Invocationhandler;
* Use Proxy.newproxyinstance to generate proxy objects;
* The object to be proxied must implement interface;
CGLib must depend on the class library of the CGLib, but it requires the class to implement any interface proxy that is the specified class that generates a subclass that overrides the method that is an inheritance.
(3), the core of the JDK is to implement the Invocationhandler interface, using the Invoke () method for face-oriented processing, call the corresponding notification. The core of Cglib is to implement the Methodinterceptor interface, using the Intercept () method for aspect-oriented processing, invoking the corresponding notification.

V. Summary

AOP is widely used to handle some system-level services with crosscutting properties, and AOP is a good complement to OOP, allowing developers to handle services with crosscutting properties in a more elegant way. Regardless of the AOP implementations, whether AspectJ or Spring AOP, they all need to dynamically generate an AOP proxy class, the difference is that the timing of generating an AOP proxy class is different: AspectJ generates an AOP proxy class at compile time and therefore has better performance, but needs to use a specific Compiler for processing, and Spring AOP uses the runtime to generate an AOP proxy class, so there is no need to use a specific compiler for processing. Because Spring AOP needs to generate an AOP proxy each time it runs, performance is slightly worse.

The Spring Series AOP

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.