Spring Aop (1) - Introduction to Aop

1 Introduction to AOP

The full name of AOP is Aspect Oriented Programming, translated into Chinese is aspect-oriented programming. Its main idea is to cut in and add specific logic at a certain point in the normal execution of the program. In the AOP framework, Aspectj has the most complete support for AOP. Spring Aop is an Aop that is implemented based on Aspectj and specifically for Spring itself. Its function is not as complete as Aspectj. It only acts on a certain method of the bean object in the Spring bean container. execution. As described in the official Spring documentation, Spring Aop and Aspectj are not in a competitive relationship, but in a relationship that complements and improves each other.

1.1 Basic principles

The basic principle of the AOP framework is basically to achieve the effect of cutting-in aspect programming for the target object through the proxy method, and Spring Aop is no exception. Spring Aop can only proxy bean objects defined in its own bean container. This is a limitation of Spring Aop. If you do not use Spring's IOC in your project, it is obviously not suitable to use Spring's Aop. There are two ways to use the proxy in Spring Aop, one is the dynamic proxy of Jdk, and the other is the proxy based on CGLIB. When our bean object implements an interface, Spring will use the Jdk dynamic proxy by default. When our bean object does not implement the interface, the CGLIB proxy will be used by default, and Spring also supports the mandatory use of CGLIB proxy when the bean object implements the interface. When the Spring Bean container initializes the bean object, it will determine whether the corresponding bean needs aspect programming, that is, whether it needs to be proxied. If so, it will be initialized as a proxy object during initialization. Let's look at a simple example based on Jdk. Suppose we define the following proxy factory, which can use the Jdk dynamic proxy mechanism to generate a corresponding proxy object from an ordinary object based on the interface it implements. For specific code and instructions, please see the following code, in which we can add some specific processing logic when the target object executes a specific method.

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyFactory {

	private static ProxyFactory instance = new ProxyFactory();
	private ProxyFactory() {}
	
	public static ProxyFactory getInstance() {
		return instance;
	}
	
	@SuppressWarnings("unchecked")
	public <T> T create(final T t) {
		return (T) Proxy.newProxyInstance(t.getClass().getClassLoader(), t.getClass().getInterfaces(), new InvocationHandler() {

			/* * 
			 * When using the created proxy object to execute the method, it will be converted to call the invoke method of the InvocationHandler object bound to the proxy object, 
			 * so that we can perform some specific processing logic on the calling situation in this method 
*/ public Object invoke ( Object proxy , Method method , Object [] args ) throws Throwable {
				 System . out . println( " The method being called is: " + method);
				 // 1. Add the processing logic before calling the method // ... Object result = null ;
				 try {
								 
			      
				
				 // 2. The target method of the target object is normally invoked 
					result = method . invoke(t, args);
					 // 3. The processing logic after the normal invocation can be added 
					// ... 
				} catch ( Exception e) {
					 // 4 , The processing logic of the method call that can be added to the target object after an exception is thrown 
					// .. 
				} finally {
					 // 5. The processing logic of the method that can be added to the target object after the execution is completed, this logic will be executed regardless of whether an exception is thrown or not
				}
				return result;
			}
			
		});
	}
	
}

The following is a simple example based on the above code. The details are as follows. Interested friends can also try it themselves.

@Test 
public  void test1() {
	 ProxyFactory proxyFactory =  ProxyFactory . getInstance();
	 // Create an object that implements the UserService interface 
	UserService userService =  new  UserServiceImpl ();
	 // Create a proxy object based on the userService object 
	UserService proxy = proxyFactory . create(userService);
	 // Call a method of the proxy object 
	User user = proxy . findById( 1 );
	 System . out . println(user);
}

The above is just a simple example, just to illustrate the general principle of Spring Aop. In fact, the proxy logic of Spring Aop is much more complicated than this. After initializing the bean, it needs to determine whether the bean needs to create a proxy object, which is usually BeanPostProcessor. Function. Interested readers can refer to the preInstantiateSingletons method of DefaultListableBeanFactory to understand the initialization process of Spring beans. For more details, please refer to the AbstractApplicationContext.refresh method.

1.2 Basic Concepts

Before understanding the usage of Spring Aop, we need to understand some important concepts in Spring Aop. The English names of these concepts are taken from Spring's official documents. These terms may appear in the original English form when they appear in this series of articles.

  • Aspect: Aspect class is the main class of aspect-oriented programming to define the correspondence between Pointcut and Advice.
  • Join Point: An entry point, a point at which a program runs, such as executing a method, in Spring AOP, a Join Point always represents the execution of a method.
  • Advice: The operation that the aspect class Aspect needs to perform at the Join Point. The types of Advice mainly include Before, After and Around. Many AOP frameworks including Spring's class will encapsulate Advice in a form similar to Interceptor, and then an Interceptor chain can be included before and after each Join Point, that is, multiple operations can be processed.
  • Pointcut: used to define the matching Join Point, it is an expression. It is often bound with Advice to specify the operation that needs to be performed at the Join Point matched by the Pointcut expression. Using Pointcut expression to match Join Point is a very important concept in AOP, which can make our Advice more independent, that is, one Advice can serve multiple JoinPoints at the same time. Spring AOP uses the Pointcut expression of Aspectj (the ancestor of AOP) by default.
  • Introduction: Used to declare additional methods and properties. New interfaces and their implementations can be introduced to the target object. For example, you can use Introduction to make a bean implement the isModified interface.
  • Target Object: The target object, which represents the object being processed by Aspect. Because Spring AOP is implemented based on runtime proxies, this object is always a proxy object.
  • Aop Proxy: A proxy object created by the AOP framework. In Spring AOP this proxy object will be generated by a JDK proxy (interface based) or a CGLIB proxy (Class based).
  • Weaving: means weaving. Such an action used to associate the aspect class Aspect with the target object, the result is that Aspect executes a specific Advice on the target object when the Join Point specified by Pointcut is executed. Weaving actions in the AOP framework can occur at compile time, class loading time, and runtime. Spring AOP's Weaving actions occur at runtime.

1.2.1 Advice type

There are three main types of Advice: Before, After and Around. Before is used before JoinPoint is executed, After is used after JoinPoint is executed (After type can also be subdivided), and Around can be used before and after JoinPoint is executed, and the execution of JoinPoint needs to be in The call is made in the Advice of the Around type, as follows:

  • Before: The Advice of the Before type will run before the Join Point is executed. Unless an exception is thrown at runtime, the Advice of the Before type will not prevent the Join Point from running.
  • After Return: The Advice of the After Return type will run after the normal execution of the Join Point (return) is completed, that is, the operation of the Join Point will return after no external exception is thrown.
  • After Throwing: The Advice of the After Throwing type will run after the Join Point throws an external exception.
  • After (finally): Advice of type After will run regardless of the execution result of Join Point.
  • Around: The Advice of the Around type will be executed around a Join Point. It can execute specific logic before the Join Point is executed, or it can execute specific logic after the Join Point is executed. It can also control whether the Join Point is executed, throws exceptions, Modify the return value, etc.

The function of Around Advice is the most powerful, and all other needs that can be satisfied by Advice can also be satisfied by using Around Advice. But Spring officially recommends us to use Around Advice a lot, but to use the Advice that is easiest and best to meet our needs. For example, if you just want to simply update the cache based on the return value after the Join Point is executed, then you use After Return Advice instead of Around Advice. This can not only make your program simpler, but also reduce the chance of your mistakes (when using Around Advice, the user needs to call JoinPoint's proceed method to let JoinPoint continue to run), and it can also reduce the complexity of the program.

Spring AOP currently only supports specific Advice processing for JoinPoint such as method execution, more specifically, it only supports specific processing logic for method execution defined by beans in the Spring Bean container. If you need to also intercept access to properties and enforce specific advice, then you might consider using Aspectj. Another point to note is that the aspect class will not be automatically proxied and cannot be used as the target class of other aspect classes, even if the Poincut target object you configure can contain the corresponding Aspect.

(Note: This article is written based on Spring 4.1.0)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326258670&siteId=291194637