首页 > 编程语言 >Java中的动态代理是什么?

Java中的动态代理是什么?

时间:2024-11-18 23:15:09浏览次数:3  
标签:Java Object 代理 public proxy 动态 method

Java的动态代理是一种在运行时动态创建代理对象的机制,主要用于在不修改原始类的情况下对方法调用进行拦截和增强。

Java动态代理主要分为两种类型:

  • 基于接口的代理(JDK动态代理):这种类型的代理要求目标对象必须实现至少一个接口。Java动态代理会创建一个实现了相同接口的代理类,然后再运行时动态生成该类的实例。这种代理的实现核心是 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口。每一个动态代理类都必须实现 InvocationHandler 接口,并且每个代理类的实例都关联到一个handler。当通过代理对象调用一个方法时,这个方法的调用就会被转发为由 InvocationHandler 接口的 invoke() 方法来进行调用。
    import java.lang.reflect.InvocationHandler;  
    import java.lang.reflect.Method;  
    import java.lang.reflect.Proxy;  
    
    // 定义接口  
    interface UserService {  
        void addUser(String userName);  
    }  
    
    // 实现接口  
    class UserServiceImpl implements UserService {  
        @Override  
        public void addUser(String userName) {  
            System.out.println("User added: " + userName);  
        }  
    }  
    
    // 实现 InvocationHandler  
    class DynamicProxyHandler implements InvocationHandler {  
        private final Object target;  
    
        public DynamicProxyHandler(Object target) {  
            this.target = target;  
        }  
    
        @Override  
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
            System.out.println("Before invoking method: " + method.getName());  
            Object result = method.invoke(target, args);  
            System.out.println("After invoking method: " + method.getName());  
            return result;  
        }  
    }  
    
    // 测试动态代理  
    public class DynamicProxyExample {  
        public static void main(String[] args) {  
            UserService userService = new UserServiceImpl();  
            InvocationHandler handler = new DynamicProxyHandler(userService);  
            
            // 创建代理对象  
            UserService proxy = (UserService) Proxy.newProxyInstance(  
                userService.getClass().getClassLoader(),  
                userService.getClass().getInterfaces(),  
                handler  
            );  
    
            proxy.addUser("Alice");  
        }  
    }

  • 基于类的代理(CGLIB动态代理):CGLIB(Code Generation Library)是一个强大的高性能的代码生成库,它可以在运行时动态生成一个目标类的子类。CGLIB代理不需要目标类实现接口,而是通过继承的方式创建代理类。因此,如果目标对象没有实现任何接口,可以使用CGLIB来创建动态代理。
    import net.sf.cglib.proxy.Enhancer;  
    import net.sf.cglib.proxy.MethodInterceptor;  
    import net.sf.cglib.proxy.MethodProxy;  
    
    // 被代理的类  
    class UserService {  
        public void addUser(String userName) {  
            System.out.println("User added: " + userName);  
        }  
    }  
    
    // CGLib动态代理  
    class CglibProxy implements MethodInterceptor {  
        @Override  
        public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable {  
            System.out.println("Before invoking method: " + method.getName());  
            Object result = proxy.invokeSuper(obj, args);  
            System.out.println("After invoking method: " + method.getName());  
            return result;  
        }  
    }  
    
    // 测试CGLib动态代理  
    public class CglibProxyExample {  
        public static void main(String[] args) {  
            Enhancer enhancer = new Enhancer();  
            enhancer.setSuperclass(UserService.class);  
            enhancer.setCallback(new CglibProxy());  
    
            // 创建代理对象  
            UserService proxy = (UserService) enhancer.create();  
            proxy.addUser("Bob");  
        }  
    }

动态代理的优缺点:

优点:

  • 解耦:代理逻辑与业务逻辑分离,易于管理和扩展。
  • 灵活性:可以在运行时灵活地改变代理逻辑,例如在不同的环境中可以选择不同的处理方式。
  • 增强功能:可以在不修改目标类的情况下增强其功能。

缺点:

  • 性能开销:由于反射的使用,动态代理相较于静态代理性能较低。
  • 调式困难:由于动态动态代理在运行时生成代理对象,跟踪和调试时可能会导致困难。调用栈中会涉及到代理类,可能使得问题的根源不易查找。

总结:

动态代理在Java中提供了一种灵活的方式来控制方法调用,广泛应用于各种场景,如AOP(面向切面编程)、框架开发等。

标签:Java,Object,代理,public,proxy,动态,method
From: https://blog.csdn.net/weixin_73526362/article/details/143840748

相关文章

  • 动态规划-二维费用问题——474.一和零
    1.题目解析 题目来源474.一和零——力扣 测试用例2.算法原理1.状态表示本题是一个二维费用的问题,如果一开始直接使用二维dp表来表示比较困难,所以不妨直接使用三维dp表先来理解:dp[i][j][k]:在区间[1,i]上选择字符串,此时在字符0的总和不大于j且字符1的总和不......
  • java 创建线程的三种方法(Thread,Runnable,Callable)ExecutorService
    1.继承Thread类2.实现Runnable接口3.实现Callable接口4.线程池1.继承Thread类packagecom.chen;//创建线程的方式:继承Thread,重写run(),调用start()开启线程//注意,线程开启不一定立即执行,由cpu调度执行publicclassTestThread2extendsThread{@Overridepublicvoid......
  • [RoarCTF 2019]Easy Java
    打开链接映入眼帘的是一个登录窗口用admin'查看一下有没有注入漏洞,回显一直是wrongpassword这个界面到别处找找看有没有线索,我们点击help按钮看看发现有一个help.docx文件未找到报错,这里是get传参,我们试试post的传参,感觉也是比较神经下载到了一个help.docx文件,我们看看是......
  • javaWeb小白项目--学生宿舍管理系统
     目录一、检查并关闭占用端口的进程二、修改Tomcat的端口配置三、重新启动Tomcat一、javaw.exe的作用二、结束javaw.exe任务的影响三、如何判断是否可以结束 结尾: 这个错误提示表明在本地启动Tomcatv9.0服务器时遇到了问题,原因是所需的端口(8005、8080)已......
  • 如何在 Ubuntu 上安装 Mosquitto MQTT 代理
    如何在Ubuntu上安装MosquittoMQTT代理Mosquitto是一个开源的消息代理,实现了消息队列遥测传输(MQTT)协议。在Ubuntu22.04上安装MQTT代理,您可以利用MQTT轻量级的TCP/IP消息平台,该平台专为资源有限的物联网(IoT)设备设计,例如带宽低或电池寿命短的设备。Mos......
  • Java子类继承父类哪些内容 C语言初阶指针数组末
    1.publicclasstest18{/*publicstaticvoidmain(String[]args){Ziz1=newZi();Ziz2=newZi("zhangsan",15);}}classFu{Stringname;intage;publicFu(){}publicFu(Stringname,intage)......
  • JAVA反序列化学习-CommonsCollections2(基于ysoserial)
    环境准备JDK1.8(8u421)这里ysoserial,我以本地的JDK8版本为准、commons-collections4(4.0以ysoserial给的版本为准)、javassist(3.12.1.GA)cc4.0、ClassPool<dependency><groupId>org.apache.commons</groupId><artifactId>commons-collections4</artifactId&......
  • 读《Effective Java》笔记 - 条目3
    条目3:利用私有构造器或枚举类型强化Singleton属性Singleton是什么?是指只能实例化一次的类。Singleton通常用于表示无状态的对象,函数,或本质上唯一的系统组件。将一个类设计为Singleton会使其客户端测试变得十分困难,因为Singleton不能被继承,我们无法创建一个用来代替它的......
  • 【CUMT】《Java语言与网络编程》(张爱娟)部分课后简答题及答案参考
    chapter1.Java概述chapter2.基本程序设计chapter3.流程控制chapter4.面向对象与类chapter5.类的进阶设计chapter6.异常处理chapter7.常用类chapter9.线程与并发编程chapter11.网络编程chapter1.Java概述1.编写、运行Java程序的基本过程是怎样的?(1)在IDE中:用jav......
  • 数据结构java:插入排序
    插入排序插入排序基本思想:直接插入排序希尔排序(缩小增量排序)插入排序基本思想:直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序中,直到所有的记录插入完为止,得到一个新的有序序列。实际......