Two methods are: 1. JDK dynamic proxy, using the reflection mechanism to generate an anonymous class that implements the proxy interface, and calling InvokeHandler before calling specific methods; 2. CGLIB dynamic proxy, using the asm open source package, Load the class file of the proxy object class and process it by modifying its bytecode to generate a subclass.
The operating environment of this tutorial: windows7 system, java8 version, DELL G3 computer.
Dynamic proxy is a very important application scenario of reflection. Dynamic proxies are often used in some Java frameworks. For example, Spring's AOP and Dubbo's SPI interface are implemented based on Java dynamic proxy.
There are two methods of dynamic proxy:
JDK dynamic proxy: using the reflection mechanism to generate an implementation proxy interface For anonymous classes, call InvokeHandler before calling specific methods.
CGLIB dynamic proxy: Use the ASM (open source Java bytecode editing library, operating bytecode) open source package to load the class file of the proxy object class, and modify its characters Section code generates subclasses to handle.
Difference: JDK agent can only generate agents for classes that implement interfaces; CGlib implements agents for classes, generates a subclass for the specified class, and overrides it The method, which is implemented through inherited classes, cannot proxy the final-modified class.
Forcing to use CGlib
<!-- proxy-target-class="false"默认使用JDK动态代理 --> <aop:aspectj-autoproxy proxy-target-class="true"/> <aop-config proxy-target-class="true"> <!-- 切面详细配置 --> </aop-config>
Specific code example:
/** * 目标接口类 */ public interface UserManager { public void addUser(String id, String password); public void delUser(String id); }
/** * 接口实现类 */ public class UserManagerImpl implements UserManager { @Override public void addUser(String id, String password) { System.out.println("调用了UserManagerImpl.addUser()方法!"); } @Override public void delUser(String id) { System.out.println("调用了UserManagerImpl.delUser()方法!"); } }
/** * JDK动态代理类 */ public class JDKProxy implements InvocationHandler { // 需要代理的目标对象 private Object targetObject; public Object newProxy(Object targetObject) { // 将目标对象传入进行代理 this.targetObject = targetObject; // 返回代理对象 return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this); } // invoke方法 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 进行逻辑处理的函数 checkPopedom(); Object ret = null; // 调用invoke方法 ret = method.invoke(targetObject, args); return ret; } private void checkPopedom() { // 模拟检查权限 System.out.println("检查权限:checkPopedom()!"); } }
/** * CGlib动态代理类 */ public class CGLibProxy implements MethodInterceptor { // CGlib需要代理的目标对象 private Object targetObject; public Object createProxyObject(Object obj) { this.targetObject = obj; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(obj.getClass()); enhancer.setCallback(this); Object proxyObj = enhancer.create(); return proxyObj; } @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object obj = null; // 过滤方法 if ("addUser".equals(method.getName())) { // 检查权限 checkPopedom(); } obj = method.invoke(targetObject, args); return obj; } private void checkPopedom() { System.out.println("检查权限:checkPopedom()!"); } }
/** * 测试类 */ public class ProxyTest { public static void main(String[] args) { UserManager userManager = (UserManager)new CGLibProxy().createProxyObject(new UserManagerImpl()); System.out.println("CGLibProxy:"); userManager.addUser("tom", "root"); System.out.println("JDKProxy:"); JDKProxy jdkProxy = new JDKProxy(); UserManager userManagerJDK = (UserManager)jdkProxy.newProxy(new UserManagerImpl()); userManagerJDK.addUser("tom", "root"); } }
// 运行结果 CGLibProxy: 检查权限checkPopedom()! 调用了UserManagerImpl.addUser()方法! JDKProxy: 检查权限checkPopedom()! 掉用了UserManagerImpl.addUser()方法!
Summary:
1. The JDK agent uses the reflection mechanism To implement aop's dynamic proxy, the CGLIB proxy uses the bytecode processing framework asm to generate subclasses by modifying the bytecode. Therefore, the jdk dynamic proxy method has higher efficiency in creating proxy objects but lower execution efficiency. cglib has lower creation efficiency and higher execution efficiency.
2. JDK dynamic proxy mechanism is a delegation mechanism. Specifically, dynamic implementation of interface classes , entrust handler to call the original implementation class method in the dynamically generated implementation class. CGLIB uses the inheritance mechanism. Specifically, the proxy class and the proxy class are inheritance relationships, so the proxy class can be assigned to the proxy class. If it is The proxy class has an interface, so the proxy class can also be assigned to the interface.
(Recommended tutorial: java introductory tutorial)
The above is the detailed content of What are the two ways of dynamic proxy?. For more information, please follow other related articles on the PHP Chinese website!