Spring AOP and springaop
In normal business processes, there are often some business logic, such as security audit and log management. They exist in every business, but they are not closely related to the actual business logic.
Figure 1
These logics are called cross-cutting logics. If you write the logic code for cross-cutting in the Business Code and scatter it in various places, it will become very difficult to maintain and the code will become too bloated.
Spring AOP provides a good way to deal with these problems.
1. AOP terminology
1. advice ). Notification refers to the target logic of real execution. For example, if you want to record logs for the system, the notification is to record logs.
2. Join point (joinpoit ). The connection point indicates when to execute the advice code. In the system, if you want to record a log of "our system is starting" before executing all start () methods, the time when the start () method is called, which is called a connection point.
Pointcut ). The cut point refers to where the advice code is executed. For example, if the start () method in a specified path is called and the advice code is executed, the specific path can be considered as a cut point. Generally, we use regular expressions to define matching classes and methods to determine the cut point.
4-section (aspect ). This section describes all the content of notifications, cut points, and connection points. It defines when and what functions are completed.
5. weaving ). Weaving refers to the process of proxy for the target object when the actual code is executed to the cut point. There are three ways to import data:
A. woven by the compiler. Special compiler support is required, such as AspectJ's weaving into the compiler. during compilation, the code is woven into the compiler.
B. When the class is loaded. The target class introduces the aspect when loading the JVM. Special classLoader support is required to change the bytecode of the target class and add new actions.
C. runtime. Use Dynamic proxy technology at runtime to act as the proxy target class. Spring AOP is used in this way.
2. Spring support for AOP
Spring provides a variety of support for AOP, which is generally divided into two ideas.
1. Use Dynamic proxy to generate proxy objects for the target class at runtime. The proxy class encapsulates the target class, intercepts calls to the notified method, and forwards the call to the real target class method call. In the proxy class, you can execute the aspect logic. Based on this mode, only method blocking is allowed. If you want to implement more fine-grained interception, such as modifying specific fields, you need to use the 2nd methods.
2. Use the AOP language specific to AspectJ. The cost of this method lies in the need to learn the AspectJ syntax.
In most cases, the first approach can meet our needs.
3 Demo
We can use the execution indicator to indicate the cut point. 2
Figure 2
The execution indicator specifies the class under which the package executes the method and will be woven into the cross-cutting logic. There are many Spring AOP demos on the Internet, but the principles are actually the same. Paste one of them here.
We need two classes. One Class (Biz) is used as the normal business logic, and the other class is used as the cross-cutting (AdviceTest ). Write a class Main test at the same time
1. Biz
1 public class Biz {2 public void doBiz () {3 System. out. println ("doing biz"); 4} 5}View Code
2. AdviceTest
1 public class AdviceTest implements Advice, MethodInterceptor {2 3 @ Override 4 public Object invoke (MethodInvocation invocation) throws Throwable {5 advice (); 6 invocation. proceed (); 7 return null; 8} 9 10 public void advice () {11 System. out. println ("this is a advice"); 12} 13 14}View Code
3. Main
1 public class Main {2 public static void main (String [] args) {3 ApplicationContext applicationContext = new ClassPathXmlApplicationContext (new String [] {"config/spring/spring-aop.xml "}); 4 Biz biz = (Biz) applicationContext. getBean ("biz"); 5 biz. doBiz (); 6} 7}View Code
4. Spring Configuration
1 <? Xml version = "1.0" encoding = "UTF-8"?> 2 <beans 3 xmlns = "http://www.springframework.org/schema/beans" 4 xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" 5 xmlns: aop = "http://www.springframework.org/schema/aop" 6 xsi: schemaLocation = "7 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 8 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 9"> 10 11 <bean id = "adviceTest" class = "aop. adviceTest "/> 12 13 <bean id =" biz "class =" aop. biz "/> 14 15 <aop: config> 16 <aop: pointcut id =" bizPointCut "expression =" execution (* aop. biz. *(..)) "/> 17 <aop: advisor pointcut-ref =" bizPointCut "advice-ref =" adviceTest "/> 18 </aop: config> 19 20 </beans>View Code
Run the Main function code and output the following code:
This is a advice
Doing biz
It can be seen that the actual biz logic has been enhanced.
4. Source Code Analysis
Spring provides two methods to generate proxy objects: JDKProxy and Cglib. The specific method used to generate the proxy objects is determined by AopProxyFactory Based on the configuration of the AdvisedSupport object. The default policy is to use JDK dynamic proxy technology if the target class is an interface. Otherwise, Cglib is used to generate a proxy. In our example, Cglib is clearly used. 3
Figure 3
Why didn't we get the Biz instance when we configured the bean of Biz? This is related to Spring's tag parsing policy for xml files. For AOP-related bean parsing, there is related code in the AopNamespaceHandler class. If you are interested, you can study it.
We continue to perform the following single-step debugging and find that the CglibAopProxy class is in place.
1 public Object intercept (Object proxy, Method method, Object [] args, MethodProxy methodProxy) throws Throwable {2 Object oldProxy = null; 3 boolean setProxyContext = false; 4 Class <?> TargetClass = null; 5 Object target = null; 6 try {7 if (this. advised. exposeProxy) {8 // Make invocation available if necessary. 9 oldProxy = AopContext. setCurrentProxy (proxy); 10 setProxyContext = true; 11} 12 // May be null. get as late as possible to minimize the time we13 // "own" the target, in case it comes from a pool... 14 target = getTarget (); 15 if (target! = Null) {16 targetClass = target. getClass (); 17} 18 List <Object> chain = this. advised. getInterceptorsAndDynamicInterceptionAdvice (method, targetClass); 19 Object retVal; 20 // Check whether we only have one InvokerInterceptor: that is, 21 // no real advice, but just reflective invocation of the target.22 if (chain. isEmpty () & Modifier. isPublic (method. getModifiers () {23 // We can skip creating a Meth OdInvocation: just invoke the target directly.24 // Note that the final invoker must be an InvokerInterceptor, so we know25 // it does nothing but a reflective operation on the target, and no hot26 // swapping or fancy proxying.27 Object [] argsToUse = AopProxyUtils. adaptArgumentsIfNecessary (method, args); 28 retVal = methodProxy. invoke (target, argsToUse); 29} 30 else {31 // We need to create a metho D invocation... 32 retVal = new CglibMethodInvocation (proxy, target, method, args, targetClass, chain, methodProxy ). proceed (); 33} 34 retVal = processReturnType (proxy, target, method, retVal); 35 return retVal; 36} 37 finally {38 if (target! = Null) {39 releaseTarget (target); 40} 41 if (setProxyContext) {42 // Restore old proxy.43 AopContext. setCurrentProxy (oldProxy); 44} 45} 46}View Code
Shamelessly paste the Code directly. We will focus on the following line.
RetVal = new CglibMethodInvocation (proxy, target, method, args, targetClass, chain, methodProxy). proceed ();
In this example, a CglibMethodInvocation execution context is created and the proceed () method is executed.
Figure 4
Finally, call the invoke () method in AdviceTest. In the invoke method of AdviceTest, We can customize the invocation. proceed () logic that we want to execute the method of the target class.
Figure 5
5. Summary
Spring AOP provides a good solution for many business-independent logic execution. This article is just a reference. In actual Spring source code, it is still complicated and requires further research.
References:
Spring In Action
Deep Spring source code analysis
Author: mayday Taro Source: Birthday.