An overview,
1. What is AOP
Aspect Oriented Programming (AOP) : Section-oriented Programming, which refers to the operation of dynamically cutting a piece of code into a specified method and a specified location during program execution. Such as: performance monitoring, logging, authority control, etc., through AOP to solve the code coupling problem, so that the responsibility is more single.
AOP techniques It uses a technique called “crosscutting” to peel apart the interior of a wrapped object and encapsulate common behavior that affects multiple classes into a reusable module named “Aspect,” or Aspect. The so-called “facets”, simply speaking, are those unrelated to the business, but encapsulated by the logic or responsibility called by business modules, which is convenient to reduce the repetitive code of the system, reduce the degree of coupling between modules, and is conducive to the future operability and maintainability
Ii. Case realization and derivation
In order to better understand the principle of AOP, we will take steps through the case. First, we will use the Spring framework to inject bean with configuration class annotation, UserService as the business code:
- UserService business code:
@Service
public class UserService {
public void queryAll(a){
System.out.println("Business Code: Query all data"); }}Copy the code
- Configure the class injection bean
@Configuration
@ComponentScan("com.star")
public class AppConfig {}Copy the code
- Bytecode is retrieved by reflection to create an object
@Test
public void AOPTest(a){
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
UserService bean = ac.getBean(UserService.class);
bean.queryAll();
}
Copy the code
If we run the AOPTest method, we can see that the console prints:
Let’s enhance the function on the basis of the above code.
1. Direct enhancement
Now we need to add a print log before and after the execution of the business code. Without AOP, we can enhance it by adding related methods directly to the service business:
@Service
public class UserService {
public void queryAll(a){
System.out.println("Before ---- Print logs before service code execution.....");
System.out.println("Business Code: Query all data");
System.out.println("After ---- Print logs before service code execution....."); }}Copy the code
This puts enhancement code and business code together, which is unreasonable, and increases coupling, which is not conducive to code expansion.
Dynamic proxy enhancement
A dynamic proxy requires a proxy class that is dynamically generated, created when bytecode is needed, loaded when it is needed, and enhanced without modifying the source code. There are two kinds of proxy mechanisms, one is dynamic proxy based on JDK, the other is dynamic proxy based on CGLib, beans without interfaces use CGLib proxy, beans with interfaces use JDK proxy. Since the interface was not used in the above example, the CGLib proxy is used here.
You can refer to the previous blog about dynamic proxies: blog.csdn.net/One_L_Star/…
@Test
public void AOPTest1(a){
final UserService bean = new UserService();
UserService cglibProducer = (UserService) Enhancer.create(bean.getClass(), new MethodInterceptor(){
/** * function: Any excuse method that executes the proxied object passes through this method *@paramProxy: reference to the proxy object *@paramMethod: the currently executed method *@paramArgs: parameters * required to execute the current method@return: has the same return value * as the proxied object method@throws Throwable
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
throws Throwable {
System.out.println("Log");
Object result = method.invoke(bean, args);
returnresult; }}); cglibProducer.queryAll(); }Copy the code
The following output is displayed after the command is executed:
You can see that after CGLib proxy, do not modify the business code on the basis of the method to enhance, and in spring AOP at the bottom, is also the use of dynamic proxy, but far more complex than the above code, if you want to delve deeper, need to see the spring source code, here only basic principles, source code a little too expensive hair.
3. AOP aspect enhancement
Finally, let’s look at how Spring is enhanced. AOP is a standard specification, and there are several ways to implement this standard specification:
- Proxy-based AOP
- @AspectJ annotation-driven facets
- Pure POJO section
- Injection AspectJ facets
These four methods are all ways to implement AOP. Here’s how to implement AOP through the annotations provided by AspectJ. However, on the Spring website, the concept of AspectJ is present, mainly because in spring2.x, the syntax of Spring AOP was too complex and Spring wanted to improve it. And the improvement of the time with the help of AspectJ syntax, programming style to complete the field AOP configuration function, here the use of AspectJ annotations to achieve.
- @ EnableAspectJAutoProxy annotations
Add @enableAspectJAutoProxy annotation to the configuration class to enable the aspect programming function. Add as follows:
@Configuration
@ComponentScan("com.star")
@EnableAspectJAutoProxy
public class AppConfig {}Copy the code
- Add section class
Use the @aspect annotation to declare a section, and use @before, @after, and other annotations to indicate join points
@Aspect
@Component
public class LogAspect {
@Pointcut("execution(* com.star.service.. *. * (..) )"
public void pointCut(a){};
@Before("pointCut()")
public void logStart(a){
System.out.println("Print logs before query....");
}
@After("pointCut()")
public void logEnd(a){
System.out.println("Print log after query....");
}
@AfterReturning("pointCut()")
public void logReturn(a){
System.out.println("Return to.... as normal after query");
}
@AfterThrowing("pointCut()")
public void logException(a){
System.out.println("Error returned after query...."); }}Copy the code
- The test run class remains unchanged
@Test
public void AOPTest(a){
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
UserService bean = ac.getBean(UserService.class);
bean.queryAll();
}
Copy the code
Run the test class directly and you can see the enhancements to the methods
Get a proxy object directly, first generate a target object, then proxy the target object, return the proxy object, and put the target object into the map
The proxy is completed at Spring initialization, when the following code is executed
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AopConfig.class);
Copy the code
Three, AOP principle understanding
1. The AOP terminology
Reference: the understanding of the term yq.aliyun.com/articles/63…
Above, we have implemented the method enhancement through AOP through the example. Now let’s understand. First, we must understand the terminology of AOP, which is embodied in the AOP aspect enhancement case above.
- Joinpoint (Joinpoint) : the smallest unit of Joinpoint is called method, each method is called Joinpoint, such as before class initialization, after class initialization, before a method is called, after the call, method throws an exception. A class or piece of program code has specific points that are boundary properties, and specific points within these points are called join points. In the above case, the methods where the @before, @after, and so on annotations are called join points.
- Pointcut: Tangent point is a set of join points, each program class has multiple join points, such as a class with two methods, these two methods are join points, that is, join points are objective things in the program class. AOP locates specific join points through “pointcuts.” Join points correspond to records in the database, while pointcuts correspond to query conditions. Pointcuts and join points are not one-to-one. A pointcut can match multiple join points.In the above case, @pointcut (“execution() com.star.service... * (..) “) “is a cut point.
Join points are a vague concept that defines where you can cut in, all the places that allow you to inform.
A pointcut defines the location where the notification is applied (with the orientation information of the notification, the specific connection point can be determined)
-
Advice: The timing and content of a join point are called Advice. Spring facets can apply five types of Advice:
-
Before: call notification Before the target method is called;
-
After notification: the notification is called After the target method has completed, regardless of what the output of the method is.
-
Post-returning notification: notification is called After successful execution of the target method;
-
After-throwing: calls notifications After the target method throws an exception;
-
Around advice: Advice wraps the notified method, performing custom behavior before and after the notified method invocation.
The advice defines what needs to be done and when to do it at a particular join point. The cut point above defines where to do it.
-
Target: Refers to the enhanced object, that is, the notified object, which is the actual business logic. In this case, UserService is the Target object
-
Introduction: Allows us to add new method properties to existing classes. By introduction, we can dynamically add the implementation logic of the interface to the business class, making the business class the implementation class of the interface.
-
Weaving: Weaving is the process of adding notifications to specific join points of the target class. AOP is like a loom that seamlessly weaves together target classes, notifications, or referrals. AOP can be woven in three ways, depending on the implementation technology:
-
Compile-time weaving, which requires a special Java compiler.
-
Class load time is woven in, which requires the use of a special class loader.
-
Dynamic proxy weaving, a way to add notification generation subclasses to the target class at run time.
-
Spring uses dynamic proxy weaving while AspectJ uses compile-time weaving and class-load weaving to create a new proxy object by applying facets to the target object.
- Proxy: When a class is woven into advice by AOP, it produces a result class. This class is called a Proxy object, which is a Proxy class that blends the original class with the advice logic.
- Aspect: The class where join points and cuts and advice are located is called an Aspect. It contains both the definition of crosscutting logic and the definition of join points. Spring AOP is the framework responsible for implementing aspects by weaving the crosscutting logic defined by the Aspect into the join points specified by the Aspect.
A combination of pointcuts’ notifications, the aspect knows all it needs to do: when/where/what
2. AOP implementation principle
Method for reference: www.cnblogs.com/stateis0/p/…
[1] Design of AOP
- At the bottom of Spring, if we configure the proxy mode, Spring creates a FactoryBean corresponding to ProxyFactoryBean for each Bean to create a proxy object for an object.
- Each Bean will be proxied by the JDK or Cglib. It depends on whether there is an interface.
- Each Bean will have multiple “method interceptors.” Note: Interceptors have two layers. The outer layer is controlled by the Spring kernel, and the inner layer is user-set, or AOP.
- When a proxy method is invoked, it passes through the outer interceptor, which determines which “inner interceptors” the method should execute based on various information about the method. The design of the inner interceptor is the design of the responsibility chain.
[2] Creation of proxy
- First, you need to create a proxy factory, which requires three important pieces of information: the interceptor array, the target object interface array, and the target object.
- When a proxy factory is created, one more default interceptor is added to the end of the interceptor array — for the final call to the target method.
- When the getProxy method is called, a proxy object (JDK or Cglib) is returned based on the condition that the number of interfaces is more than zero.
Note: When you create a proxy object, you create an outer interceptor, which is the Spring kernel interceptor. Used to control the entire AOP process.
[3] Invocation of proxy
- When a proxy object is called, the outer interceptor is triggered.
- The outer interceptor creates the inner interceptor chain based on the proxy configuration information. During creation, the expression is used to determine whether the current interception matches the interceptor. The interceptor chain design pattern is the chain of responsibility pattern.
- When the chain ends, the default interceptor on the tail of the proxy is triggered to invoke the target method. Finally return.
As shown in figure:
Call procedure: