• JDK动态代理原理解析


    代理模式

    定义

    由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。

    解决什么问题

    • 被访问对象应做控制
    • 访问对象时添加一些额外功能

    静态代理

    • 代理类和被代理类实现相同的接口,代码重复,维护有难度
    • 代理对象只服务于一种类型的对象,如果要服务多类型对象则要为每一种对象都进行代理,要代理的种类规模稍大时就显得力不从心了

    动态代理

    在程序运行期间根据需要动态创建代理类及其实例来完成具体的功能。

    • JDK动态代理
    • cglib动态代理

    JDK动态代理

    1. 创建被代理的对象和类
    1. 创建InvocationHandler接口的实现类,在invoke方法中实现代理逻辑
    1. 通过Proxy类的静态方法newProxyInstance(ClassLoader loader, Class[] interfaces,InvocationHandler h)创建一个代理对象
    1. 使用代理对象

    关键代码示例

    1. package com.jd.designpattern.proxy;
    2. import java.lang.reflect.InvocationHandler;
    3. import java.lang.reflect.Method;
    4. /**
    5. * 代理Handler
    6. */
    7. public class ProxyHandler implements InvocationHandler {
    8. private Object object;
    9. public ProxyHandler(Object object){
    10. this.object = object;
    11. }
    12. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    13. System.out.println("动态代理 - 执行前:" + method.getName());
    14. method.invoke(object, args);
    15. System.out.println("动态代理 - 执行后:" + method.getName());
    16. return null;
    17. }
    18. }

    其中的wirte()方法是将生成的代理类写入到本地,用idea打开后可查询生成的class到底是什么

    1. package com.jd.test.proxy;
    2. import com.jd.designpattern.proxy.ProxyHandler;
    3. import com.jd.designpattern.proxy.ProxySubject;
    4. import com.jd.designpattern.proxy.RealSubject;
    5. import com.jd.designpattern.proxy.Subject;
    6. import org.junit.Test;
    7. import sun.misc.ProxyGenerator;
    8. import java.io.FileNotFoundException;
    9. import java.io.FileOutputStream;
    10. import java.io.IOException;
    11. import java.lang.reflect.InvocationHandler;
    12. import java.lang.reflect.Proxy;
    13. /**
    14. * 代理模式测试类
    15. * @author jubingtao
    16. * @date 2020-4-27
    17. */
    18. public class ProxyTest {
    19. @Test
    20. public void testStaticProxy(){
    21. //获取代理
    22. Subject subject = new ProxySubject();
    23. subject.request();
    24. }
    25. @Test
    26. public void testDynamicProxy(){
    27. Subject subject = new RealSubject();
    28. InvocationHandler handler = new ProxyHandler(subject);
    29. Subject proxySubject = (Subject) Proxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), handler);
    30. proxySubject.request();
    31. write();
    32. }
    33. private void write(){
    34. String path = "D:/$Proxy0.class";
    35. byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy0",RealSubject.class.getInterfaces());
    36. FileOutputStream out = null;
    37. try {
    38. out = new FileOutputStream(path);
    39. out.write(classFile);
    40. out.flush();
    41. } catch (FileNotFoundException e) {
    42. e.printStackTrace();
    43. } catch (IOException e) {
    44. e.printStackTrace();
    45. } finally {
    46. try {
  • 相关阅读:
    如何在 Windows 10 中安装 Azure Data Studio 1.39.1
    Matlab基础一、关于初始化数组,数据矩阵,三维数据,字符串数组
    第16章-Spring AOP中的基础API
    一天的忙碌,一路的飞翔,我的回家之旅
    SpringBoot幂等性防重token令牌实现方案(redis+annoation+interceptor实现)
    进制转换算法(通用,极简)
    震坤行亮相2023工博会,并荣获第23届中国工博会“CIIF信息技术奖”
    三、python Django ORM操作数据库[命令、postgresql操作]
    为什么说Java 中的公平锁(Fair Lock)并不是完全公平的,而是近似公平的
    进程间通信:无名管道+有名管道
  • 原文地址:https://blog.csdn.net/long290046464/article/details/134044548