• 动态代理模式——JDK动态代理


      今天,我就来讲一下动态代理的设计模式。

      动态代理的意义在于生成一个代理对象,来代理真实对象,从而控制真实对象的访问。操作动态代理需要两个步骤:一、代理对象和真实对象建立代理关系。二、实现代理对象的代理逻辑方法。

      在Java中,有很多的动态代理技术。如:JDK、CGLIB、Javassist、ASM,其中最常用的动态代理技术有两种:一种是JDK动态代理,这是JDK自带的功能;另一种就是CGLIB,这是第三方提供的一种技术。

      这次主要讲的是JDK动态代理和CGLIB动态代理。在JDK动态代理中,我们必须使用接口,而CGLIB就不需要。

    JDK 动态代理

      JDK 动态代理是 java.lang.reflect.* 包提供的方式,它必须借助一个接口才能产生代理对象,所以我们先定义一个接口。代码如下:

    1 public interface HelloWorld {
    2 
    3     public void sayHelloWorld();
    4 }

      然后提供实现类来实现此接口。代码如下:

    public class HelloWorldImpl implements HelloWorld {
    
        @Override
        public void sayHelloWorld() {
            System.out.println("Hello World! 动态代理学习篇");
        }
    
    }

      这是最简单的 Java 接口与实现类的关系。这时我们开始今天学习的内容,JDK动态代理。我们先要建立代理对象和真实服务对象的关系,然后实现代理逻辑。

      在 JDK 动态代理中,要实现代理逻辑类必须去实现 java.lang.reflect.InvocationHandler 接口,它里面定义了一个 invoke 方法,并且提供接口数组用于下挂代理对象。代码如下:

    public class JdkProxy implements InvocationHandler {
        
        //真实对象
        private Object target = null;
        
        /**
         * 建立代理对象和真实对象的代理关系,并返回代理对象
         * @param obj 真实对象
         * @return           代理对象
         */
        public Object bind(Object target){
            this.target = target;
            return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        }
    
        /**
         * 代理方法逻辑
         * @param proxy    代理对象
         * @param method 当前调度方法
         * @param args 当前方法的参数
         * @return 代理结果返回
         * @throws 异常
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("进入代理逻辑方法");
            System.out.println("在调度真实对象之前的服务");
            //相当于调用 sayHelloWorld 的方法
            Object obj = method.invoke(target, args);
            System.out.println("在调度真实对象之后的服务");
            return obj;
        }
    
    }

      第1步,建立代理对象和真实对象的关系。这里使用 bind 方法去完成,方法里面首先用类的属性 target 保存了真实对象,然后通过如下代码建立并生成代理对象。

    Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);

      其中 newProxyInstance 方法包含三个参数。

      第一个参数为:类加载器。

      第二个参数为:把生成的动态代理对象下挂在哪些接口下。

      第三个参数为:定义实现方法逻辑的代理类,this 表示当前对象,它必须实现 InvocationHandler 接口方法的 invoke 方法,它就是代理逻辑方法的现实方法。

      第2步,实现代理逻辑方法。 invoke 方法可以实现代理逻辑, invoke 方法的三个参数的意义如下:

      proxy:代理对象,就是 bind 方法生成的对象。

      method:当前调度的方法。

      args: 调度方法的参数。

    测试一下JDK动态代理方法。代码如下:

    public class TestProxy {
        
        public static void main(String[] args) {
            JdkProxy jdkTest = new JdkProxy();
            HelloWorld proxy = (HelloWorld)jdkTest.bind(new HelloWorldImpl());
            proxy.sayHelloWorld();
            
        }
    
    }

    测试结果如下:

      这就是 JDK 动态代理,它是一种常用的动态代理。

  • 相关阅读:
    微软紧急安全公告:当心SQL攻击爆发
    婴儿
    感冒了
    System.IO.FileAttributes
    mssql数据库,无法用语句实现“强制还原”功能
    好大的风
    无聊的游戏
    JZOJ 4276【NOIP2015模拟10.28A组】递推
    JZOJ 4289.Mancity
    单词检索(search)
  • 原文地址:https://www.cnblogs.com/HHHY/p/11746709.html
Copyright © 2020-2023  润新知