首页后端开发其他后端知识Java的动态代理有几种方式,如何理解?

Java的动态代理有几种方式,如何理解?

时间2024-03-28 16:58:03发布访客分类其他后端知识浏览1166
导读:这篇文章给大家分享的是Java的动态代理的相关内容,下文介绍了JDK动态代理和CGLIB动态代理。对于刚接触Java的朋友可能不是很了解Java的动态代理,文中介绍得很详细,有需要的朋友可以参考,接下来就跟随小编一起了解看看吧。...

这篇文章给大家分享的是Java的动态代理的相关内容,下文介绍了JDK动态代理和CGLIB动态代理。对于刚接触Java的朋友可能不是很了解Java的动态代理,文中介绍得很详细,有需要的朋友可以参考,接下来就跟随小编一起了解看看吧。

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

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

动态代理的方式有两种:

  • JDK动态代理:利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

  • CGLIB动态代理:利用ASM(开源的Java字节码编辑库,操作字节码)开源包,将代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

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

强制使用CGlib


具体代码示例:

/**
 * 目标接口类
 */
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的动态代理的内容就介绍到这,感兴趣的朋友可以参考,希望能对大家有帮助,想要了解更多Java的动态代理,大家可以关注网络其它的相关文章。

文本转载自PHP中文网

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!


若转载请注明出处: Java的动态代理有几种方式,如何理解?
本文地址: https://pptw.com/jishu/655074.html
JavaScript怎样实现分页效果 Spring Cloud常见组件包括哪些,功能是什么?

游客 回复需填写必要信息