catalogue
1.1.2 complete the entry code test
1.1.4 how does the business layer control transactions
1.1.4 business code - problem description
1.2.1 characteristics of agent mode
1.3.1 description of JDK agent
1.4 dynamic agent JDK mode case
1.5 dynamic agent - CGLIB agent
1.6 summary of JDK agent and CGlib agent (elevation / Architecture)!!!
2.1.2 hierarchical code structure
2.1.3 hierarchical code structure
1. Agent mode
1.1 create project
1.1.1 create project
1.1.2 complete the entry code test
1.1.3 editing UserService
1.1.3.1 edit Service interface
package com.jt.service; public interface UserService { void addUser(); }
1.1.3.2 edit ServiceImpl implementation class
package com.jt.service; import org.springframework.stereotype.Service; @Service public class UserServiceImpl implements UserService{ @Override public void addUser() { System.out.println("New user"); } }
1.1.4 how does the business layer control transactions
Transaction: can guarantee the / atomicity / consistency / persistence / isolation of data
Note: the transaction of the database needs to be considered during the operation of the business layer. The code structure is as follows:
package com.jt.service; import org.springframework.stereotype.Service; @Service public class UserServiceImpl implements UserService{ @Override public void addUser() { try { System.out.println("Open database transaction"); System.out.println("New user"); int a = 1/0; System.out.println("Commit database transactions"); }catch (Exception e){ System.out.println("Transaction rollback"); } } }
1.1.4 business code - problem description
- If there are multiple methods, each method needs to control the transaction. The code repetition rate is high
- The business layer service should only deal with business and should not be coupled with transaction code. Otherwise, it has poor scalability and high coupling
How to solve it: use the agent mechanism to solve it
1.2 agency mechanism
1.2.1 characteristics of agent mode
Note: generally, the agent mode is adopted, and the main purpose is to decouple. Put the common method (function / business) into the agent object. The business layer can focus on business execution
1.2.1 agency characteristics
- Why use proxy? Because they are inconvenient (no resources)
- The role of agents? The agent has to solve (extend) some practical problems
- User end execution target method!!!
1.3 dynamic agent JDK mode
1.3.1 description of JDK agent
- JDK proxy mode is an API provided by java natively, and there is no need to import packages
- JDK agent requirements: the agent must Either interface or implement interface
- Flexibility: the agent as like as two peas! (same method)
1.3.2 editing agent class
package com.jt.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class JDKProxy { //Pass in the target object to get the name of the proxy object //Extension of method using proxy object public static Object getProxy(Object target){ //1. Get class loader ClassLoader classLoader = target.getClass().getClassLoader(); //2. Get interface array type Class[] interfaces = target.getClass().getInterfaces(); //3. Callback method when proxy object executes method (invocationhandler is executed when proxy object calls method) return Proxy.newProxyInstance(classLoader,interfaces,invocationHandler(target)); } //The target object must be passed public static InvocationHandler invocationHandler(Object target){ return new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Transaction on"); //Gets the return value of the target method Object result = method.invoke(target,args); System.out.println("Transaction commit"); return result; } }; } }
1.3.3 edit test class
package com.jt; import com.jt.config.SpringConfig; import com.jt.proxy.JDKProxy; import com.jt.service.UserService; import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class TestSpring { @Test public void demo1(){ ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); //Get target object UserService userService = context.getBean(UserService.class); //userService.addUser(); //Get proxy object UserService proxy = (UserService) JDKProxy.getProxy(userService); //The proxy object executes the method and calls the invoke method proxy.addUser(); } }
1.4 dynamic agent JDK mode case
Requirement: you are required to calculate the running time of addUser() method? Dynamic agent is required
1.4.1 edit proxy object
public static Object getTimePorxy(Object target){ ClassLoader classLoader = target.getClass().getClassLoader(); Class[] interfaces = target.getClass().getInterfaces(); return Proxy.newProxyInstance(classLoader,interfaces,invocationHandlerTime(target)); } //The target object must be passed public static InvocationHandler invocationHandlerTime(Object target){ return new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //start time long startTime = System.currentTimeMillis(); //Let the target method execute the result Object result = method.invoke(target,args); long endTime = System.currentTimeMillis(); System.out.println("time consuming:"+(endTime - startTime)); return result; } }; }
1.4.2 edit test method
package com.jt; import com.jt.config.SpringConfig; import com.jt.proxy.JDKProxy; import com.jt.service.UserService; import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class TestSpring { @Test public void demo1(){ ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); //Get target object UserService userService = context.getBean(UserService.class); System.out.println(userService.getClass()); //userService.addUser(); //Get proxy object UserService proxy = (UserService) JDKProxy.getTimePorxy(userService); System.out.println(proxy.getClass()); //The proxy object executes the method and calls the invoke method proxy.addUser(); } }
1.5 dynamic agent - CGLIB agent
1.5.1 CGLIB description
JDK proxy: it is required to have / implement an interface. If there is no interface, the JDK proxy cannot execute normally
cglib proxy: it is required that the agent can have an interface or not The proxy object is a subclass of the target object Override subclass methods
1.5.2 CGLIB agent mode
package com.jt.proxy; 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 CGlibProxy { public static Object getProxy(Object target){ //1. Create an intensifier object Enhancer enhancer = new Enhancer(); //2. Set parent target object enhancer.setSuperclass(target.getClass()); //3. The callback method is defined and called when the proxy object executes the target method enhancer.setCallback(getMethodInterceptor(target)); //4. Create proxy object return enhancer.create(); } //target object needs to be passed public static MethodInterceptor getMethodInterceptor(Object target){ return new MethodInterceptor() { @Override public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("Transaction start"); //Execution target method Object result = method.invoke(target,args); System.out.println("Transaction commit"); return result; } }; } }
1.5.3 cglib agent test class
@Test public void demo2(){ ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); //Get target object UserService userService = context.getBean(UserService.class); UserService proxy = (UserService) CGlibProxy.getProxy(userService); System.out.println(proxy.getClass()); proxy.addUser(); }
1.6 summary of JDK agent and CGlib agent (elevation / Architecture)!!!
1. JDK requires that there must be or implement interfaces. cglib can create proxy objects with or without interfaces. Proxy objects are subclasses of target objects
2. JDK proxy tool API: proxy.newproxyinstance (class loader, interface array, invocationHandler interface)
3. CGlib proxy tool API: Enhancer enhancer object gets the proxy object enhancer.create(); Callback interface
MethodInterceptor interface
4. Execute target method in JDK
-method.invoke(target,args);
Execute target method in CGlib
-method.invoke(target,args);
2. Introduction to spring AOP
2.1 create project
2.1.1 basic structure
2.1.2 hierarchical code structure
2.1.3 hierarchical code structure
<!--introduce AOPjar Package file--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
2.2 AOP
2.2.1 AOP introduction
In the software industry, AOP is the abbreviation of Aspect Oriented Programming, which means: Aspect Oriented Programming, a technology to realize the unified maintenance of program functions through precompiled mode and dynamic agent during operation. AOP is the continuation of OOP, a hot spot in software development, an important content in Spring framework, and a derivative paradigm of functional programming. AOP can isolate each part of business logic, reduce the coupling between each part of business logic, improve the reusability of program, and improve the efficiency of development.
Summary: AOP in Spring uses proxy objects to extend methods without modifying the source code
2.2.2 AOP introduction case
2.2.2.1 edit configuration class
@Configuration @ComponentScan("com.jt") //Packet scanning @EnableAspectJAutoProxy //Turn on AOP public class SpringConfig { }
2.2.2.2 edit section class
package com.jt.aop; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Component //Leave the class to Spring container management!!! @Aspect //Identifies that the class is a facet public class SpringAOP { /** * Knowledge review: AOP uses dynamic agents to expand the target method * Formula: facet = pointcut expression + notification method * Pointcut expression: if the target object satisfies the judgment (if) of the pointcut expression, spring automatically creates a proxy object for it * Notification method: an encapsulation method that extends the target method * ID of the bean of the target object: userserviceimpl * Pointcut expression: * 1. bean("bean ID of) * AOP Rule: if the target object satisfies the pointcut expression, the notification method is executed */ @Pointcut("bean(userServiceImpl)") public void pointcut(){ } //Pre - Notification: executed before the target method is executed @Before("pointcut()") public void before(){ System.out.println("I'm an advance notice!!!!"); } }
2.2.2.3 edit test class
package com.jt; import com.jt.config.SpringConfig; import com.jt.service.UserService; import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class TestSpring { @Test public void demo1(){ ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); //It is the target object, but if it matches the pointcut expression, the proxy object is generated dynamically UserService userService = context.getBean(UserService.class); System.out.println(userService.getClass()); //Because it is a proxy object, the method can be extended userService.addUser(); } }
2.3 common notification types
package com.jt.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; @Component //Leave the class to Spring container management!!! @Aspect //Identifies that the class is a facet public class SpringAOP { /** * Knowledge review: AOP uses dynamic agents to expand the target method * Formula: facet = pointcut expression + notification method * Pointcut expression: if the target object satisfies the judgment (if) of the pointcut expression, spring automatically creates a proxy object for it * Notification method: an encapsulation method that extends the target method * ID of the bean of the target object: userserviceimpl * Pointcut expression: * 1. bean("bean ID of) * AOP Rule: if the target object satisfies the pointcut expression, the notification method is executed */ @Pointcut("bean(userServiceImpl)") public void pointcut(){ } //1. Pre notification: executed before the target method is executed @Before("pointcut()") public void before(){ System.out.println("I'm an advance notice!!!!"); } //2. Post notification: executed after the target method is executed @AfterReturning("pointcut()") public void afterReturn(){ System.out.println("I'm a post notification!!!!"); } //3. Exception notification: this notification is executed when the target method reports an error @AfterThrowing("pointcut()") public void afterThrowing(){ System.out.println("I'm an exception notification!!!!"); } //4. Final notice: the notice to be executed after the target method @After("pointcut()") public void after(){ System.out.println("The final notice shall be executed"); } //5. Focus on mastering the surrounding notice: implement it before and after the implementation of the target method. Control the target method @Around("pointcut()") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("Before execution of surround notification!!!!"); //The underlying layer calls the invoke method of the dynamic agent to execute the target method Object result = joinPoint.proceed(); System.out.println("After the notification is executed!!!!"); return result; } }