1, What is the proxy model
Proxy mode: provides an avatar for an object to control access to the object. That is, through the agent
Object to access the target object
Advantages: Based on the realization of the target object, additional function operations can be enhanced, that is, the function of the target object can be extended.
The proxied object can be a remote object, an object with high creation cost, or an object requiring security control
The agent mode has different forms, mainly including three kinds of static agent, dynamic agent and Cglib agent.
2, Static proxy
When using a static proxy, you need to define an interface or parent class. The proxy object (i.e. the target object) implements the same interface or inherits the same parent class with the proxy object
Special reminder: the proxy object and the target object should implement the same interface, and then call the method of the target object by calling the same method.
Specific examples:
1) Define an interface: lTeacherDao
2) The target object TeacherDAO implements the interface ITeacherDAO
3) Using the static proxy method, you need to implement ITeacherDAO in the proxy object TeacherDAOProxy
4) When called, the target object is called by calling the method of the proxy object
1. Define an interface: lTeacherDao
package Proxy; //Interface public interface lTeacherDao { void teach();//Training Methods }
2. Create the target class and implement the interface
package Proxy; public class TeacherDao implements lTeacherDao{ @Override public void teach() { System.out.println("The teacher is teaching"); } }
3. Create proxy class, proxy target class
package Proxy; //Proxy object public class TeacherDAOProxy implements lTeacherDao{ private TeacherDao target;//Target object, aggregated through interface //constructor public TeacherDAOProxy(TeacherDao target) { this.target = target; } @Override public void teach() { System.out.println("The agent starts and performs some operations"); target.teach(); System.out.println("Submit"); } }
4. Create proxy object and target object to implement proxy
package Proxy; public class Client { public static void main(String[] args) { //Initialize the proxied object (target object) TeacherDao teacherDao = new TeacherDao(); //Initialize the proxy object and pass the proxy object into the proxy object TeacherDAOProxy teacherDAOProxy = new TeacherDAOProxy(teacherDao); //Through the proxy object, call the method to the proxy object //That is, the method of the proxy object is executed, and the proxy object calls the method of the target object teacherDAOProxy .teach(); } }
The agent starts and performs some operations The teacher is teaching Submit
3, Dynamic agent
1) The proxy object does not need to implement the interface, but the target object must implement the interface, otherwise the dynamic proxy cannot be used
2) The generation of proxy object is to dynamically build proxy object in memory by using JDK API
3) Dynamic agent is also called JDK agent and interface agent
1. Define an interface: lTeacherDao
package Proxy; //Interface public interface lTeacherDao { void teach();//Training Methods }
2. Create the target class and implement the interface
package Proxy; public class TeacherDao implements lTeacherDao{ @Override public void teach() { System.out.println("The teacher is teaching"); } }
3. Create classes to dynamically generate proxy objects
InvocationHandler interface and Proxy class
InvocationHandler interface is an interface implemented by the calling handler of proxy proxy instance. Each proxy instance has an associated calling handler; When a method is called by a proxy instance, the method call is encoded and dispatched to the invoke method of the calling handler.
When we call a method through a dynamic proxy object, the call of this method will be forwarded to the invoke method implementing the InvocationHandler interface class to call, as shown in the following invoke method:
/** * proxy:The real proxy object of proxy class proxy is com.sun.proxy.$Proxy0 * method:The Method object of the real Method of an object we want to call * args:Refers to the parameters passed by the proxy object method */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
Proxy class is a class used to create a proxy object. It provides many methods, but the most commonly used method is newProxyInstance.
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
The purpose of this method is to create a proxy class object, which receives three parameters.
ClassLoader loader:Specifies the class loader used by the current target object,Method for obtaining loader Class<?>[] interfaces:The interface type implemented by the target object,Type validation using generic methods InvocationHandler h:In event processing, when executing the method of the target object, the event processor method will be triggered, and the currently executed target object method will be passed in as a parameter
package Proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; //Proxy object public class ProxyFactory { //Maintain a target object, object private Object target; //Constructor to initialize the target public ProxyFactory(Object target) { this.target = target; } //Generate a proxy object for the target object public Object getProxyInstance() { // public static Object newProxyInstance(ClassLoader loader, // Class<?>[] interfaces, // InvocationHandler h) //Classloader: Specifies the class loader used by the current target object, and the method to get the loader is fixed // Class<?> [] interfaces: the interface type implemented by the target object. Use the generic method to confirm the type // InvocationHandler h: in event processing, when the method of the target object is executed, the event handler method will be triggered, and the currently executed target object method will be passed in as a parameter return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("JDK Agent start"); //The reflection mechanism calls the target object Object invoke = method.invoke(target, args); System.out.println("JDK Agent end"); return invoke; } }); } }
4. Implementation agent
package Proxy; public class Client { public static void main(String[] args) { //Create target object lTeacherDao target= new TeacherDao(); //Create a proxy object for the target object and convert it to lTeacherDao lTeacherDao proxyInstance=(lTeacherDao)new ProxyFactory(target).getProxyInstance(); System.out.println("proxyInstance"+proxyInstance.getClass());//proxyInstanceclass com.sun.proxy.$Proxy0 indicates that a proxy object is generated in memory //Proxy target method through proxy object proxyInstance.teach(); } }
proxyInstanceclass com.sun.proxy.$Proxy0 JDK Agent start The teacher is teaching JDK Agent end
4, cglib proxy
1) Both static proxy and JDK proxy patterns require that the target object implement an interface, but sometimes the target object only implements an interface
It is a separate object and does not implement any interface. At this time, you can use the target object subclass to implement the proxy - this is cglib proxy
2) Cglib proxy is also called subclass proxy. It constructs a subclass object in memory to achieve the function of the target object
Some books also attribute cglib agents to dynamic agents.
3)Cglib is a powerful high-performance code generation package. It can extend java classes and implement java interfaces at runtime. It is widely used by many AOP frameworks, such as Spring AOP, to implement method interception
4) How to select proxy mode in AOP programming:
1. The target object needs to implement the interface and use JDK proxy
2. The target object does not need to implement the interface and is represented by cglib
5) The bottom layer of cglib package is to convert bytecode and generate new classes by using bytecode processing framework ASM
Instance class diagram:
public class TeacherDao { public void teach(){ System.out.println("The teacher teaches, I am cglib Proxy, no need to implement interface"); } }
CGLIB agent is adopted for implementation: the asm version package needs to be imported to implement the MethodInterceptor interface
- import net.sf.cglib.proxy.Enhancer;
- import net.sf.cglib.proxy.MethodInterceptor;
- import net.sf.cglib.proxy.MethodProxy;
- Cglib dynamic agent:
- (you need to import two jar packages, asm-5.0.3.jar and cglib-3.1.jar. You can choose your own version)
package cglib; import java.lang.ref1ect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy. MethodProxy ; public class ProxyFactory implements MethodInterceptor { //Maintain a target object private object target; //Constructor, passing in an object to be represented public ProxyFactory(object target) { this.target = target; } //Return a proxy object: it is the proxy object of the target object public object getProxyInstance(){ //1. Create a tool class Enhancer enhancer = new Enhancer(); //2 set parent class enhancer.setsuperclass(target.getclass()); //3 set callback function enhancer.setcailback(this); //Create a subclass object, the proxy object return enhancer.create(); } //Overriding the intercept method will call the target object's method @ override public 0bject intercept(Object arg0,Nethod arg1,Object[] arg2,NethodProxy arg3) throws Throwable { System.out.print1n("cg1ib proxy pattern~~ ka); object returnVal = method.invoke(target,args); System.out.print1n("cglib proxy pattern~~~Submit"); return returnVal; } }
package cglib; public class Cglib { public static void main(String[] args) { //Create target object lTeacherDao target= new TeacherDao(); //Create a proxy object for the target object and convert it to lTeacherDao lTeacherDao proxyInstance=(lTeacherDao)new ProxyFactory(target).getProxyInstance(); //Proxy target method through proxy object proxyInstance.teach(); } }
5, JDK and CGLIB dynamic agent summary
-
JDK dynamic agent can only generate agents for classes that implement interfaces, not for classes. It is implemented using Java reflection technology, and the process of generating classes is more efficient.
-
CGLIB implements a proxy for a class. It mainly generates a subclass of a specified class and covers its methods. It is implemented using the asm bytecode framework. The related execution process is more efficient. The process of generating a class can be compensated by the cache. Because it is inheritance, it is better not to declare this class or method as final
-
JDK proxy does not need the support of a third-party library. It only needs the JDK environment to proxy. Usage conditions: implement InvocationHandler + generate proxy object using Proxy.newProxyInstance + the proxy object must implement the interface
-
CGLib must rely on CGLib's class library, but it needs classes to implement any interface proxy. It generates a subclass from the specified class and overrides the methods in it. It is an inherited proxy, but it is recommended to use JDK in the environment of interface programming;