The implementation principle of Spring AOP

Source: Internet
Author: User
Tags aop

AOP (Aspect Orient programming), which we generally call aspect-oriented programming, complements the object-oriented approach to the crosscutting concerns that are distributed across modules in the system, such as transaction management, logging, caching, and so on. The key to the AOP implementation is the AOP proxy, which is automatically created by the AOP framework, which is mainly divided into static agent and dynamic agent, static proxy is ASPECTJ, and dynamic agent is represented by spring AOP. This article will analyze and introduce the implementation of ASPECTJ and spring AOP respectively.

Implementing AOP with AspectJ's compile-time enhancements

As mentioned earlier, ASPECTJ is an enhancement of static proxies, so-called static proxies are the AOP framework that generates an AOP proxy class during the compilation phase, and therefore is also known as compile-time enhancement.

For example, let me give you a sample. First of all we have a common Hello class

Public?class? Hello? {
?? Public?void?sayhello ()? {
? ? ? ? System.out.println ("Hello");
? ?}

?? Public?static?void?main (string[] args)? {
? ? ? ? Hello h =?new? Hello ();
???? H.sayhello ();
? ?}
}

Write a aspect using ASPECTJ

Public?aspect Txaspect {
?? Void?around (): Call (void? Hello.sayhello ()) {
? ? ? ? System.out.println ("Start transaction ...");
???? proceed ();
? ? ? ? System.out.println ("End of Transaction ...");
? ?}
}

This simulates a transaction scenario, similar to spring's declarative transaction. Compiling with ASPECTJ compiler

Ajc?-d?.? Hello.java? Txaspect.aj

Once the compilation is complete, run this Hello class and you can see the following output

Start a transaction ...
Hello
End of transaction ...

Obviously, AOP is already in effect, so how does ASPECTJ add new functionality to the Hello class without modifying the Hello class?

Take a look at the compiled Hello.class

Public?class? Hello? {
????? Hello ()? {
? ?}

?? Public?void?sayhello ()? {
? ? ? ? System.out.println ("Hello");
? ?}

?? Public?static?void?main (string[] args)? {
? ? ? ? Hello h =?new? Hello ();
????. Sayhello_aroundbody1$advice (H, Txaspect.aspectof (), (aroundclosure) null);
? ?}
}

As you can see, the original Hello.java of this analogy is a bit more code, which is the static proxy of ASPECTJ, which will weave aspect into Java bytecode during the compile phase, and it will run as an AOP object after being enhanced.

public void ajc$around$com_listenzhangbin_aop_txaspect$1$f54fe983 (Aroundclosure ajc$aroundclosure) {
? ? ? ? System.out.println ("Start transaction ...");
???? ajc$around$com_listenzhangbin_aop_txaspect$1$f54fe983proceed (Ajc$aroundclosure);
? ? ? ? System.out.println ("End of Transaction ...");
? ?}

The logic of execution can be seen more clearly from the aspect compiled class file. The proceed method is the callback that executes the method in the proxy class.

Using Spring AOP

Unlike static proxies for ASPECTJ, the dynamic proxy used by Spring AOP, the so-called dynamic Proxy means that the AOP framework does not modify bytecode, but instead generates an AOP object temporarily in memory for the method, which contains all the methods of the target object. And the method of the original object is enhanced with the specific pointcut.

There are two main ways of dynamic Proxy in Spring AOP, JDK dynamic agent and Cglib dynamic agent. The JDK dynamic agent receives the Proxied class through reflection, and requires that the class being proxied must implement an interface. The core of the JDK dynamic agent is the Invocationhandler interface and the proxy class.

If the target class does not implement an interface, spring AOP chooses to use Cglib to dynamically proxy the target class. CGLIB (Code Generation Library) is a code-generated class library that dynamically generates subclasses of a class at run time, noting that CGLIB is a dynamic proxy that is done by inheritance, so if a class is marked as final, Then it is not possible to use Cglib to do dynamic proxies.

To verify the above statement, a simple test can be done. First, test the implementation of the interface.

Define an interface

Public?interface? person {
? ? String?sayhello (String?name);
}

Implementation class

@Component
Public?class? Chinese?implements? Person? {

? [Email protected]
? [Email protected]
????? String?sayhello (String name)? {
? ? ? ? System.out.println ("--SayHello ()--");
????? return?name +? "Hello, AOP";
? ?}

?? public?void?eat (String food)? {
? ? ? ? System.out.println ("I'm eating:"? + food);
? ?}

}

The @timer annotation Here is a general note that I define myself to mark Pointcut.

Define Aspect

@Aspectbr/> @Component
< p="">

? [email protected] ("@annotation (Com.listenzhangbin.aop.Timer)")
?? public void Pointcut () {
? ?}

? [email protected] ("Pointcut ()")
?? public void before () {
? ? ? ? System.out.println ("before");
? ?}
}

Run

@SpringBootApplicationbr/> @RestController
< p="">

??//This must be injected using the person interface
? [email protected]
?? private person Chinese;

? [email protected] ("/test")
?? public void Test () {
???? Chinese.sayhello ("Listen");
? ? ? ? System.out.println (Chinese.getclass ());
? ?}

?? Public?static?void?main (string[] args) {
? ? ? ? Springapplication.run (Springbootdemoapplication.class, args);
? ?}
}

Output

Before
--SayHello ()--
Class?com.sun.proxy. $Proxy 53

You can see that the type is com.sun.proxy. $Proxy 53, which is the proxy class mentioned earlier, so spring AOP uses the JDK's dynamic proxy.

Take a look at the case where the interface is not implemented, modify the Chinese class

@Component
Public?class? Chinese? {

? [email protected]
// ? [email protected]
????? String?sayhello (String name)? {
? ? ? ? System.out.println ("--SayHello ()--");
????? return?name +? "Hello, AOP";
? ?}

?? public?void?eat (String food)? {
? ? ? ? System.out.println ("I'm eating:"? + food);
? ?}

}

Run

@SpringBootApplicationbr/> @RestController
< p="">

??//Directly injected with the Chinese class
? [email protected]
?? private Chinese Chinese;

? [email protected] ("/test")
?? public void Test () {
???? Chinese.sayhello ("Listen");
? ? ? ? System.out.println (Chinese.getclass ());
? ?}

?? Public?static?void?main (string[] args) {
? ? ? ? Springapplication.run (Springbootdemoapplication.class, args);
? ?}
}

Output

Before
--SayHello ()--
Class com.listenzhangbin.aop.chinese$ $EnhancerBySpringCGLIB $$56b89168

You can see that the class is cglib enhanced, which is the dynamic proxy. The Cglib agent here is the proxy for spring AOP, the so-called AOP Proxy, where the AOP proxy class dynamically weaves the enhanced processing in the pointcut.

Summary

ASPECTJ enhances the target object at compile time, the dynamic agent of Spring AOP is dynamically enhanced at each run time, and the AOP proxy object is generated, the difference is that the timing of generating AOP proxy object is different, and the static proxy method of ASPECTJ has better performance. However, ASPECTJ requires a specific compiler for processing, and spring AOP does not require specific compiler processing.

The implementation principle of Spring 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.