The description of dynamic agents has been partially described in the previous two articles Detailed interpretation of dynamic agent and A simple description of dynamic agent , the dynamic proxy of JDK can only generate the proxy for the class that implements the interface. The dynamic proxy of cglib is to implement the proxy for the class, which we can use flexibly. We interpret these two kinds of dynamic agents through the example of car running.
1, JDK dynamic agent
Car interface
package proxy; public interface Car { public void run(); }
Car implementation class
package proxy; public class CarImpl implements Car{ public void run() { System.out.println("car running"); } }
Car agent class
package proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; //JDK dynamic agent class public class CarHandler implements InvocationHandler{ //Object of real class private Object car; //Constructor assigned to real class public CarHandler(Object obj){ this.car = obj; } //When a proxy class executes a method, it calls this method public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before"); Object res = method.invoke(car, args); System.out.println("after"); return res; } }
main method
package proxy; import java.lang.reflect.Proxy; public class main { public static void main(String[] args) { CarImpl carImpl = new CarImpl(); CarHandler carHandler = new CarHandler(carImpl); Car proxy = (Car)Proxy.newProxyInstance( main.class.getClassLoader(), //First parameter, get ClassLoader carImpl.getClass().getInterfaces(), //The second parameter, get the interface of the proxy class carHandler);//The third parameter, an InvocationHandler object, indicates which InvocationHandler object my dynamic proxy object will be associated with when I call a method proxy.run(); } }
Operation results
before car running after
Through the three parameters in the above example, we can see that the dynamic proxy of JDK depends on the interface. The input parameter must have the interface of the proxied class, that is, carImpl.getClass().getInterfaces(). If some classes do not implement the interface, the JDK proxy cannot be used, which requires the use of cglib dynamic proxy.
2, Cglib dynamic agent
Car without interface
package proxy; public class CarNoInterface { public void run() { System.out.println("car running"); } }
cglib proxy class
package proxy; import java.lang.reflect.Method; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; public class CglibProxy implements MethodInterceptor{ private Object car; /** * Create proxy object * * @param target * @return */ public Object getInstance(Object object) { this.car = object; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.car.getClass()); // Callback method enhancer.setCallback(this); // Create proxy object return enhancer.create(); } @Override public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) throws Throwable { System.out.println("The beginning of things"); proxy.invokeSuper(obj, args); System.out.println("The end of things"); return null; } }
main method
package proxy; import java.lang.reflect.Proxy; public class main { public static void main(String[] args) { CglibProxy cglibProxy = new CglibProxy(); CarNoInterface carNoInterface = (CarNoInterface)cglibProxy.getInstance(new CarNoInterface()); carNoInterface.run(); } }
Result output
The beginning of things car running The end of thingsIn the above two examples, we have seen the division of labor between the two dynamic agents. In the actual development, we can flexibly arrange whether to use interfaces or classes to proxy according to the needs.