• 技术文章 >Java >java教程

    动态代理的两种方式是什么

    青灯夜游青灯夜游2022-01-06 17:32:05原创169

    两种方式为:1、JDK动态代理,利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理;2、CGLIB动态代理,利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

    本教程操作环境:windows7系统、java8版、DELL G3电脑。

    动态代理是反射的一个非常重要的应用场景。动态代理常被用于一些 Java 框架中。例如 Spring 的 AOP ,Dubbo 的 SPI 接口,就是基于 Java 动态代理实现的。

    动态代理的方式有两种:

    区别:JDK代理只能对实现接口的类生成代理;CGlib是针对类实现代理,对指定的类生成一个子类,并覆盖其中的方法,这种通过继承类的实现方式,不能代理final修饰的类。

    强制使用CGlib

    <!-- proxy-target-class="false"默认使用JDK动态代理 -->
    <aop:aspectj-autoproxy proxy-target-class="true"/>
    
    <aop-config proxy-target-class="true">
    <!-- 切面详细配置 -->
    </aop-config>

    具体代码示例:

    /**
     * 目标接口类
     */
    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()方法!

    总结:

    1、JDK代理使用的是反射机制实现aop的动态代理,CGLIB代理使用字节码处理框架asm,通过修改字节码生成子类。所以jdk动态代理的方式创建代理对象效率较高,执行效率较低,cglib创建效率较低,执行效率高;

    2、JDK动态代理机制是委托机制,具体说动态实现接口类,在动态生成的实现类里面委托hanlder去调用原始实现类方法,CGLIB则使用的继承机制,具体说被代理类和代理类是继承关系,所以代理类是可以赋值给被代理类的,如果被代理类有接口,那么代理类也可以赋值给接口。

    (推荐教程:java入门教程

    以上就是动态代理的两种方式是什么的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    上一篇:java入门简单小项目有哪些 下一篇:没有了

    相关文章推荐

    • Java中关于动态代理原理分析• JDK如何实现底层动态代理• Java动态代理的原理• JDK动态代理和CGLIB区别• 静态代理和动态代理的区别是什么?

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网