Spring series courses - AOP programming
Chapter one: static agent design pattern
1. Why do you need agent design pattern
1.1 problems
-
In Java EE layered development, which layer is the most important for us
DAO ---> Service --> Controller JavaEE In layered development, the most important thing is Service layer
-
What code is included in the Service layer?
Service In layer = Core functions(Dozens of lines and hundreds of codes) + Additional features(Additional functions) 1. Core functions Business operation DAO call 2. Additional features 1. Not a business 2. not essential 3. The amount of code is very small Transactions, logs, performance...
-
How about writing additional functions in the Service layer?
Service The angle of the caller of the layer( Controller):Need in Service Additional functions for layer writing. Software designer: Service Layer does not require additional functionality
-
Solutions in real life
2. Agent design mode
1.1 concept
Add additional functionality to the original class (target) through the proxy class Benefits: benefits to primitive classes(target)Maintenance of
1.2 interpretation of terms
1. Target class original class It refers to business class (Core functions --> Business operation DAO call) 2. Target method Target class(Primitive class)The method in is the target method(Original method) 3. Additional features (Additional functions) Log, transaction, performance
1.3 core elements of agent development
proxy class = Target class(Primitive class) + Additional features + Primitive class(Target class)Implement the same interface landlord or landlady ---> public interface UserService{ m1 m2 } UserServiceImpl implements UserService{ m1 ---> Business operation DAO call m2 } UserServiceProxy implements UserService m1 m2
1.4 coding
Static proxy: manually write a proxy class (. Java. Class) for each original class
1.5 problems of static agent
1. There are too many static files, which is not conducive to project management UserServiceImpl UserServiceProxy OrderServiceImpl OrderServiceProxy 2. Poor maintenance of additional functions The modification of additional functions in the proxy class is complex(trouble)
The second chapter is the dynamic agent development of Spring
1. The concept of spring dynamic proxy
Concept: the proxy class is the original class(Target class)Add additional features Benefits: benefits to primitive classes(Target class)Maintenance of
2. Build a development environment
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.1.14.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.8</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.3</version> </dependency>
3. Development steps of spring dynamic agent
-
Create original object (target object)
public class UserServiceImpl implements UserService { @Override public void register(User user) { System.out.println("UserServiceImpl.register Business operation + DAO "); } @Override public boolean login(String name, String password) { System.out.println("UserServiceImpl.login"); return true; } }
<bean id="userService" class="com.baizhiedu.proxy.UserServiceImpl"/>
-
Additional features
MethodBeforeAdvice interfaceAdditional functions are written in the implementation of the interface and run before the original method is executed.
public class Before implements MethodBeforeAdvice { /* Function: you need to write the additional functions that run before the execution of the original method in the before method */ @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("-----method before advice log------"); } }
<bean id="before" class="com.baizhiedu.dynamic.Before"/>
-
Define pointcuts
Entry point: where additional functions are added Purpose: the programmer decides to add additional functions to the original method according to his own needs register login Simple test: all methods are used as entry points and add additional functions.
<aop:config> <aop:pointcut id="pc" expression="execution(* *(..))"/> </aop:config>
-
Assembly (2 3 integration)
Meaning of expression: all methods are added before Additional features of <aop:advisor advice-ref="before" pointcut-ref="pc"/>
-
call
Objective: to obtain Spring The dynamic proxy object created by the factory and called ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml"); be careful: 1. Spring The factory passes through the original object id Value gets the proxy object 2. After obtaining the proxy object, you can store the object by declaring the interface type UserService userService=(UserService)ctx.getBean("userService"); userService.login("") userService.register()
4. Dynamic agent detail analysis
-
Where is the dynamic proxy class created by Spring?
Spring At runtime, the framework uses dynamic bytecode technology to JVM Created, running in JVM Internally, after the procedure is completed, it will communicate with JVM Disappear together What is dynamic bytecode technology:Through the third dynamic bytecode framework, in JVM Create the bytecode of the corresponding class, and then create the object. When the virtual machine ends, the dynamic bytecode disappears. Conclusion: dynamic agents do not need to define class files, they are JVM It is created dynamically during operation, so it will not cause too many static agents and class files, which will affect project management.
-
Dynamic agent programming simplifies agent development
When creating proxy objects of other target classes (original classes) without changing the additional functions, you only need to specify the original class(target)Object.
-
The maintainability of additional functions of dynamic agent is greatly enhanced
-
Chapter 3: detailed explanation of Spring dynamic proxy
1. Detailed explanation of additional functions
-
MethodBeforeAdvice analysis
1. MethodBeforeAdvice Interface function: additional function operation is performed before the original method is executed. public class Before1 implements MethodBeforeAdvice { /* Function: you need to write the additional functions that run before the execution of the original method in the before method Method: The original method to which the extra functionality is added login method register method showOrder method Object[]: The parameter of the original method added by the additional function. String name,String password User Object: The original object UserServiceImpl added by the additional function OrderServiceImpl */ @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("-----new method before advice log------"); } } 2. before How to use the three parameters of the method in practice. before In practice, the parameters of the method will be used as needed. They may not be used or may not be used at all. Servlet{ service(HttpRequest request,HttpResponse response){ request.getParameter("name") --> response.getWriter() ---> } }
-
Methodinterceptor (method interceptor)
methodinterceptor Interface: additional functions can be run before, after and before the execution of the original method as required.
public class Arround implements MethodInterceptor { /* invoke Function of the method: additional functions are written in invoke Before the original method of additional functions After the original method Before and after the original method execution Determine: how does the original method work Parameter: method invocation (Method): the original method added by the additional function login register invocation.proceed() ---> login function register function Return value: Object: the return value of the original method Date convert(String name) */ @Override public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("-----Additional features log----"); Object ret = invocation.proceed(); return ret; } }
Additional functionality runs after the original method is executed
@Override public Object invoke(MethodInvocation invocation) throws Throwable { Object ret = invocation.proceed(); System.out.println("-----Additional functionality runs after the original method is executed----"); return ret; }
Additional functionality runs before and after the original method is executed
What additional functions are added before and after the execution of the original method? affair @Override public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("-----Additional functionality runs before the original method is executed----"); Object ret = invocation.proceed(); System.out.println("-----Additional functionality runs after the original method is executed----"); return ret; }
Additional functionality runs when the original method throws an exception
@Override public Object invoke(MethodInvocation invocation) throws Throwable { Object ret = null; try { ret = invocation.proceed(); } catch (Throwable throwable) { System.out.println("-----The original method throws an exception to perform additional functions ---- "); throwable.printStackTrace(); } return ret; }
MethodInterceptor affects the return value of the original method
The return value of the original method, directly as invoke Method, MethodInterceptor Does not affect the return value of the original method MethodInterceptor Affects the return value of the original method Invoke Method instead of directly returning the running result of the original method. @Override public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("------log-----"); Object ret = invocation.proceed(); return false; }
2. Detailed explanation of entry point
The entry point determines where additional functions are added(method) <aop:pointcut id="pc" expression="execution(* *(..))"/> exection(* *(..)) ---> All methods are matched a b c 1. execution() Pointcut function 2. * *(..) Pointcut expression
2.1 pointcut expression
-
Method pointcut expression
* *(..) --> All methods * ---> Modifier return value * ---> Method name ()---> Parameter table ..---> No requirements for parameters (Whether there are parameters or not, any number of parameters and any type of parameters are OK)
-
Define the login method as the entry point
* login(..) # Define register as the entry point * register(..)
-
The login method is defined, and the login method has two string type parameters as the entry point
* login(String,String) #Note: for types not in java.lang package, the fully qualified name must be written * register(com.baizhiedu.proxy.User) # .. Can be used with specific parameter types * login(String,..) --> login(String),login(String,String),login(String,com.baizhiedu.proxy.User)
-
Precise method entry point limitation
Modifier return value package.class.method(parameter) * com.baizhiedu.proxy.UserServiceImpl.login(..) * com.baizhiedu.proxy.UserServiceImpl.login(String,String)
-
-
Class pointcut
Specify a specific class as the pointcut(Where additional features are added),Naturally, all methods in this class will add corresponding additional functions
-
Grammar 1
#All methods in the class add additional functionality * com.baizhiedu.proxy.UserServiceImpl.*(..)
-
Grammar 2
#Ignore package 1. Class has only one level package com.UserServiceImpl * *.UserServiceImpl.*(..) 2. Class has multi-level packages com.baizhiedu.proxy.UserServiceImpl * *..UserServiceImpl.*(..)
-
-
Package pointcut expression practice
Specify where the package is added as additional functions. All classes and methods in the natural package will add additional functions
-
Grammar 1
#All classes in the pointcut package must be in the proxy, not in the sub package of the proxy package * com.baizhiedu.proxy.*.*(..)
-
Grammar 2
#The pointcut is in effect for both the current package and its sub packages * com.baizhiedu.proxy..*.*(..)
-
2.2 pointcut function
Pointcut function: used to execute pointcut expressions
-
execution
The most important pointcut function has the most complete functions. Execution method pointcut expression class pointcut expression package pointcut expression Disadvantages: execution Execute the pointcut expression, which is troublesome to write execution(* com.baizhiedu.proxy..*.*(..)) Note: other pointcut function simplifications are execution The writing complexity is completely consistent in function
-
args
Function: mainly used for functions(method) Parameter matching Pointcut: method parameter must be a parameter of type 2 strings execution(* *(String,String)) args(String,String)
-
within
Function: it is mainly used for matching class and package pointcut expressions Entry point: UserServiceImpl This class execution(* *..UserServiceImpl.*(..)) within(*..UserServiceImpl) execution(* com.baizhiedu.proxy..*.*(..)) within(com.baizhiedu.proxy..*)
4.@annotation
Function: add additional functions for methods with special annotations <aop:pointcut id="" expression="@annotation(com.baizhiedu.Log)"/>
-
Logical operation of pointcut function
It refers to integrating multiple pointcut functions to work together to complete more complex requirements
-
and operation
Case: login Two strings of parameters at the same time 1. execution(* login(String,String)) 2. execution(* login(..)) and args(String,String) Note: unlike operations, it is used for pointcut functions of the same type Case: register Methods and login Method as a starting point execution(* login(..)) or execution(* register(..))
-
or operation
Case: register Methods and login Method as a starting point execution(* login(..)) or execution(* register(..))
-
Chapter 4: AOP programming
1. AOP concept
AOP (Aspect Oriented Programing) Aspect oriented programming = Spring Dynamic agent development The program development with aspect as the basic unit completes the construction of the program by coordinating and calling each other section = breakthrough point + Additional features OOP (Object Oritened Programing) object-oriented programming Java The program development with object as the basic unit completes the construction of the program through the cooperation and call between objects POP (Producer Oriented Programing) Process oriented(Methods and functions)programming C The program development with process as the basic unit completes the construction of the program through the cooperation and call between processes
AOP Concept of: The essence is Spring Get dynamic agent development, and add additional functions to the original class through the agent class. Benefits: it is conducive to the maintenance of the original class be careful: AOP Programming cannot replace OOP,OOP Programming is intentionally supplemented.
2. Development steps of AOP programming
1. Original object 2. Additional features (MethodInterceptor) 3. breakthrough point 4. Assembly section (Additional features+breakthrough point)
3. Definition of terms
section = breakthrough point + Additional features geometry noodles = spot + Same nature
The fifth chapter is the underlying implementation principle of AOP
1. Core issues
1. AOP How to create a dynamic proxy class(Dynamic bytecode Technology) 2. Spring How does a factory create a proxy object Through the of the original object id Value to get the proxy object
2. Creation of dynamic proxy class
2.1 dynamic agent of JDK
- Detailed explanation of Proxy.newProxyInstance method parameters
-
code
public class TestJDKProxy { /* 1. Borrow class loader TestJDKProxy UserServiceImpl 2. JDK8.x front final UserService userService = new UserServiceImpl(); */ public static void main(String[] args) { //1 create original object UserService userService = new UserServiceImpl(); //2. Create dynamic agent with JDK /* */ InvocationHandler handler = new InvocationHandler(){ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("------proxy log --------"); //Original method run Object ret = method.invoke(userService, args); return ret; } }; UserService userServiceProxy = (UserService)Proxy.newProxyInstance(UserServiceImpl.class.getClassLoader(),userService.getClass().getInterfaces(),handler); userServiceProxy.login("suns", "123456"); userServiceProxy.register(new User()); } }
2.2 dynamic agent of cglib
CGlib The principle of creating a dynamic proxy: the parent-child inheritance relationship creates a proxy object, with the original class as the parent class and the proxy class as the child class. This can not only ensure the consistency of the two methods, but also provide a new implementation in the proxy class(Additional features+Original method)
-
CGlib encoding
package com.baizhiedu.cglib; import com.baizhiedu.proxy.User; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class TestCglib { public static void main(String[] args) { //1 create original object UserService userService = new UserService(); /* 2 Creating dynamic proxy objects by cglib Proxy.newProxyInstance(classloader,interface,invocationhandler) Enhancer.setClassLoader() Enhancer.setSuperClass() Enhancer.setCallback(); ---> MethodInterceptor(cglib) Enhancer.create() ---> agent */ Enhancer enhancer = new Enhancer(); enhancer.setClassLoader(TestCglib.class.getClassLoader()); enhancer.setSuperclass(userService.getClass()); MethodInterceptor interceptor = new MethodInterceptor() { //Equivalent to InvocationHandler --- invoke @Override public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("---cglib log----"); Object ret = method.invoke(userService, args); return ret; } }; enhancer.setCallback(interceptor); UserService userServiceProxy = (UserService) enhancer.create(); userServiceProxy.login("suns", "123345"); userServiceProxy.register(new User()); } }
-
summary
1. JDK Dynamic agent Proxy.newProxyInstance() Create the implementation class of the proxy through the interface 2. Cglib Dynamic agent Enhancer Proxy class created by inheriting the parent class
3. How does spring factory process original objects
-
Train of thought analysis
-
code
public class ProxyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } @Override /* Proxy.newProxyInstance(); */ public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { InvocationHandler handler = new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("----- new Log-----"); Object ret = method.invoke(bean, args); return ret; } }; return Proxy.newProxyInstance(ProxyBeanPostProcessor.class.getClassLoader(),bean.getClass().getInterfaces(),handler); } }
<bean id="userService" class="com.baizhiedu.factory.UserServiceImpl"/> <!--1. realization BeanPostProcessor Processing 2. Pair in configuration file BeanPostProcessor Configure --> <bean id="proxyBeanPostProcessor" class="com.baizhiedu.factory.ProxyBeanPostProcessor"/>
Chapter 6: annotation based AOP programming
1. Development steps of annotation based AOP programming
-
Original object
-
Additional features
-
breakthrough point
-
Assembly section
# Additional functions @ Around are defined through the facet class Pointcuts are defined @Around("execution(* login(..))") @Aspect Section class package com.baizhiedu.aspect; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; /* 1. Additional features public class MyArround implements MethodInterceptor{ public Object invoke(MethodInvocation invocation){ Object ret = invocation.proceed(); return ret; } } 2. breakthrough point <aop:config <aop:pointcut id="" expression="execution(* login(..))"/> */ @Aspect public class MyAspect { @Around("execution(* login(..))") public Object arround(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("----aspect log ------"); Object ret = joinPoint.proceed(); return ret; } }
<bean id="userService" class="com.baizhiedu.aspect.UserServiceImpl"/> <!-- section 1. Additional features 2. breakthrough point 3. Assembly section --> <bean id="arround" class="com.baizhiedu.aspect.MyAspect"/> <!--inform Spring Annotation based AOP programming--> <aop:aspectj-autoproxy />
2. Details
-
Pointcut reuse
Pointcut reuse: define a function in the facet class@Pointcut Annotation defines pointcut expressions in this way, which is more conducive to pointcut reuse in the future. @Aspect public class MyAspect { @Pointcut("execution(* login(..))") public void myPointcut(){} @Around(value="myPointcut()") public Object arround(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("----aspect log ------"); Object ret = joinPoint.proceed(); return ret; } @Around(value="myPointcut()") public Object arround1(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("----aspect tx ------"); Object ret = joinPoint.proceed(); return ret; } }
-
How dynamic agents are created
AOP The bottom layer implements two proxy creation methods 1. JDK Create a proxy object by creating a new implementation class through the implementation interface 2. Cglib Make new subclasses by inheriting the parent class Create proxy object Default AOP Programming underlying applications JDK Dynamic proxy creation method If switching Cglib 1. Annotation based AOP development <aop:aspectj-autoproxy proxy-target-class="true" /> 2. conventional AOP development <aop:config proxy-target-class="true"> </aop>
Chapter 7, a pit in AOP development
Pit: in the same business class, there are only the outermost methods for mutual calls between business methods,Is the addition of additional features(The internal methods are called in an ordinary way. They all call the original method). If you want the inner method to call the method of the proxy object, you must AppicationContextAware Get the factory, and then get the proxy object. public class UserServiceImpl implements UserService, ApplicationContextAware { private ApplicationContext ctx; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.ctx = applicationContext; } @Log @Override public void register(User user) { System.out.println("UserServiceImpl.register Business operation + DAO "); //throw new RuntimeException("test exception"); //The login method -- > core function of the original object is called /* Design purpose: login method of proxy object -- > additional functions + core functions ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext2.xml"); UserService userService = (UserService) ctx.getBean("userService"); userService.login(); Spring Factory heavyweight resources should create only one factory in an application */ UserService userService = (UserService) ctx.getBean("userService"); userService.login("suns", "123456"); } @Override public boolean login(String name, String password) { System.out.println("UserServiceImpl.login"); return true; } }
Chapter VIII summary of AOP stage knowledge
Class loading process:
Load (load the class file into the memory and instantiate an object of java.lang.Class class in the Java heap memory), verify (ensure that the class file meets the requirements of the virtual machine), prepare (allocate memory for the class variable and set the initial value of the variable in the class. If it is final type, a constant will be generated as the value of this variable during compilation, and then assign this constant to the final variable in the preparation stage) Parsing (replacing the symbolic references in the constant pool with direct references), initialization (initializing class variables and other resources according to the subjective plan of the program. The initialization phase is the process of executing the class constructor () method. It is the automatic generation of the Javac compiler), use and uninstall. The three parts of verification, preparation and parsing are collectively referred to as connection.
.
Class loader:
3 types: startup classloader (% JRE home% / LIB), extension classloader (% JRE home% / lib / ext), application classpath (classpath)
Parental delegation model:
If a class loader receives a class loading request, it will not try to load the class itself, but delegate the request to the parent class loader to complete it. This is true for class loaders at each level. Therefore, all loading requests should eventually be transmitted to the top-level startup class loader, only
When the parent loader reports that it cannot complete the load request (it does not find the required class in its search scope), the child loader will try to complete the load by itself