Having seen how to use Spring for AOP development in the previous articles, this article introduces the underlying implementation of dynamic proxies.
AOP programming concepts
AOP: Aspect Oriented Programming = Spring dynamic proxy development. The program development with section as the basic unit completes the program construction through the batch coordination and mutual call between sections. Aspect = pointcut + extra functionalityOOP: ObjectOriented Programming: Object-oriented Programming, based on the object as the basic unit of program development, through the process of batch cooperation, mutual call, complete the program constructionPOPProcedure Oriented Programming (function, method) : to process as the basic unit of program development, through the process of mutual cooperation, mutual call, complete the program constructionCopy the code
The essence of AOP programming is Spring dynamic proxy development, which adds extra functionality to the original classes through proxy classes. Note that AOP programming is not a substitute for OOP functionality and is a powerful complement.Copy the code
Review the development steps of AOP programming:
- The original object
- Additional features (MethodBeforeAdvice, MethodInterceptor)
- Pointcuts (pointcut expressions)
- The assembly
Aspect = pointcut + extra functionalityCopy the code
Core issues:
1.How does AOP create proxy classes: through dynamic bytecode technology2.How does the Spring factory process the creation of a proxy object from the id of the original objectCopy the code
Dynamic proxy implementation
Spring dynamic proxy is implemented in two ways. One is the DYNAMIC proxy technology of JDK, but the dynamic proxy technology provided by Cglib open source framework.
2.1 JDK Dynamic Proxy
JDK dynamic proxies must be interface-based, that is, our target class must implement an interface. Let’s give an example where UserService and UserServiceImpl are omitted.
The JDK provides Proxy. NewInstance (ClassLoader var0, Class<? >[] var1, InvocationHandler var2) method classes implement dynamic proxy technology. @param: interfaces: an array of interfaces implemented by the original object @param: InvocationHandler: Extra functionality here InvocatioHandler is also an interface, so we need to pass as an implementation. This interface has a Method that needs to be implemented: Object Invoke (Object Proxy, Method Method, Object[] args); @param Object proxy: represents the proxy Object, ignored, do not use @param Methdod Method: represents additional functionality added to the original method @param Object[] args: parameters of the original method @return: Object: The return value of the original method is written much like our previous MethodInterceptor, because that's how it's implemented underneath. How should we write our direct programCopy the code
public class JDKProxyTest{
public static void main(String[] args){
// 1. Create the original object
Userservice userService = new UserServiceImpl();
// 2. Create a dynamic proxy class
UserService proxy = (UserService)Proxy.newInstance(userService.getClass.getClassLoader() ,userService.getClass.getInterfaces() , new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[]args){
// Extra features in front
Object obj = method.invoke(userService, args);
// Add extra functions to the rear
returnobj; }}); proxy.login("abc"."123456"); }}Copy the code
We add the extra functionality we want to the implementation method in the InvocationHandler interface and invoke the original method by calling method.invoke(). Original method return values to return at the same time, this time we need to use the interface to receive the proxy object (because the proxy objects and primitive object implements the same interface), should pay attention to the proxy objects are dynamically generated, so we may can not find his specific source, when he calls the method we use, additional functions can be performed.
Matters needing attention:
The class loader is used to load the class bytecode file into the JVM. The virtual machine automatically assigns a ClassLoader to the. Class file of each Class. The dynamic proxy Class has no source file, but is generated using dynamic bytecode technology, which writes the bytecode directly to the JVM. The JVM does not assign a ClassLoader to a dynamic proxy Class because it does not have a. Classs file. However, if a dynamic proxy Class does not have a. Classs file, it can only borrow one. Instead of using the JDK's Class fetch, it is not a Class loader.Copy the code
2.2 CgLib dynamic proxy
The above mentioned JDK dynamic proxy technology implementation. However, the JDK dynamic proxy technology has a drawback, is that the original class must implement an interface, if the original class does not implement any interface, then the JDK dynamic proxy class can not be implemented. Cglib can do that.
Cglib dynamic proxy principle: The proxy class created by Cglib is implemented through inheritance, which inherits the original class. The original class is the parent class and the proxy class is the subclass, ensuring that the methods are the same. You don't need to implement the interface.Copy the code
Code implementation:
public class UserService{
public boolean login(String name, String password){
System.out.println("login...");
}
public void register(User user){
System.out.println("register..."); }}/ / test class
class Test{
/** Enhancer.setClassLoader(); * /
public static void main(String[] args){
UserService userService = new UserService();
Enhancer enhancer = new Enhancer();
enhander.setClassLoader(Test.class.getClassLoader());
enhander.setSuperClass(userService.class);
MethodInteceptor interceptor = new MethodInterceptor(){
@Override
public Object(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable{
System.out.println("----log-----");
Object obj = method.invoke(userService, args);
returnobj; }}; enhancer.setCallBack(interceptor); UserService proxy = (UserService)Enhancer.create(); proxy.login("abc"."123");
proxy.register(newUser()); }}Copy the code
Conclusion:
- JDK dynamic Proxy, proxy.newinstance: Implementation class for creating proxies through interfaces
- CGlib: dynamic proxy, Enhancer, inherited through parent and child classes
How does the Spring factory create proxy objects
Above we talked about the implementation of two dynamic proxies in Spring. With dynamic proxy techniques, proxy objects can be created. So in Spring, why do we get proxy objects from the id of the original bean? Let’s look at how he works. In fact, it is mainly implemented through the BeanPostProcessor interface. This interface was introduced earlier.
In the process of processing, we created his dynamic proxy object and returned it. So the object we get is a dynamic proxy object. So let’s write a case.
public interface UserService{
void register(User user);
boolean login(String name, String password)
}
public class UserServiceImpl implements UserService{
@Override
public void register(User user){
System.out.println("registe----")}@Override
public boolean login(String name, String password){
System.out.println("login-----")}}public class ProxyBeanPostProcessor implements BeanPostProcessor{
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException{
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException{
return Proxy.newInstance(this.getClass.getClassLoader(), bean.getClass.getInterfaces,new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args){
System.out.println("---log advice ---");
Object ret = method.invoke(bean, args);
returnret; }}); }}Copy the code
<bean id="userService" class="com.xxx.UserServiceImpl" />
<bean id="proxy" class="com.xxx.ProxyBeanPostProcessor" />
Copy the code
In the spring source code, it is through a class called AbstractautoXyCreator. This class is designed to create proxy objects, and its essence is to implement the BeanPostProcessor interface and create proxy objects in the method.
Well, that’s all we have to say about some of the concepts and underlying implementations of dynamic proxies.