Java Proxy动态代理

简介: 1. 动态代理概念:代理对象存在的价值: 主要用于拦截对真实业务对象的访问。代理对象有什么方法: 一般来说,真实业务对象具有什么方法,那么代理对象就会具备相应的方法。

1. 动态代理概念:

  • 代理对象存在的价值: 主要用于拦截对真实业务对象的访问。
  • 代理对象有什么方法: 一般来说,真实业务对象具有什么方法,那么代理对象就会具备相应的方法。

2. 设计要素

  • 代理谁?
    须设计一个类变量,以及一个构造函数,记住代理类代理哪个对象。
  • 如何生成代理对象?
    设计一个方法生成代理对象(在方法内编写代码生成代理对象是此处编程的难点)

3. Proxy类

Java提供了一个Proxy类,调用它的newInstance方法可以生成某个对象的代理对象,使用该方法生成代理对象时,需要三个参数:

  • 生成代理对象使用哪个类装载器。
  • 生成哪个对象的代理对象,通过接口指定。
  • 生成的代理对象的方法里干什么事,由开发人员编写handler接口的实现来指定。

4. 注意

  • Proxy类负责创建代理对象时,如果指定了handler(处理器),那么不管用户调用代理对象的什么方法,该方法都是调用处理器的invoke方法。
  • 由于invoke方法被调用需要三个参数:代理对象、方法、方法的参数,因此不管代理对象哪个方法调用处理器的invoke方法,都必须把自己所在的对象、自己(调用invoke方法的方法)、方法的参数传递进来。

5. 约定:要想创建某一个对象的代理对象,那么该对象必须实现一个接口。

6. 简单示例

1). 创建接口Person

public interface Person {
    /**
     * 唱歌
     */
    void sing();
    /**
     * 跳舞
     */
    void dance();
}

2). 创建实现Person接口的PersonImpl类

public class PersonImpl implements Person{

    @Override
    public void sing() {
        System.out.println("开始唱歌");
    }

    @Override
    public void dance() {
        System.out.println("开始跳舞");
    }

}

3). 创建代理类

public class PersonImplProxy {
    
    private Person person = new PersonImpl();
    
    /**
     * 创建代理
     * @return 返回值是接口类型
     */
    public Person createProxy() {
        /**
         * 产生某个对象的代理对象
         * ClassLoader loader    当前代理对象的类加载器
         * Class<?>[] interfaces 代理对象的接口
         * InvocationHandler h   InvocationHandler对象
         */
        return (Person) Proxy.newProxyInstance(PersonImplProxy.class.getClassLoader(), person.getClass().getInterfaces(), new InvocationHandler() {
            
            /**
             * @param proxy 把代理对象自身传进去
             * @param method 代表当前调用的方法
             * @param args 当前调用方法的参数
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // 编写代码
                return null;
            }
        });
    }
    
}

4). 编写Demo类中主函数main()

public class Demo {
    public static void main(String[] args) {
        PersonImplProxy proxy = new PersonImplProxy();
        Person person = proxy.createProxy();
        person.sing();
        person.dance();
    }
}

5). 实现代理对象中的createProxy方法中的invoke方法

public class PersonImplProxy {
    
    private Person person = new PersonImpl();
    
    /**
     * 创建代理
     * @return 返回值是接口类型
     */
    public Person createProxy() {
        /**
         * 产生某个对象的代理对象
         * ClassLoader loader    当前代理对象的类加载器
         * Class<?>[] interfaces 代理对象的接口
         * InvocationHandler h   InvocationHandler对象
         */
        return (Person) Proxy.newProxyInstance(PersonImplProxy.class.getClassLoader(), person.getClass().getInterfaces(), new InvocationHandler() {
            
            /**
             * @param proxy 把代理对象自身传进去
             * @param method 代表当前调用的方法
             * @param args 当前调用方法的参数
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // 编写代码
                // 获取方法名
                String methodName = method.getName();
                if ("sing".equals(methodName)) {
                    System.out.println("啦啦啦啦啦啦啦啦");
                    method.invoke(person, args);
                } else if ("dance".equals(methodName)) {
                    System.out.println("哈哈哈哈哈哈哈哈");
                    method.invoke(person, args);
                } else {
                    System.out.println("啊啊啊啊啊啊啊啊");
                }
                return null;
            }
        });
    }
    
}

6). 调用main方法,打印结果:


img_026a0e246e61560fcc3a69e22fdf4417.png
图1.png

7. 高级进阶--接口方法中带参数带返回值

1). 创建Person接口

public interface Person {
    /**
     * 唱歌
     * @param name 歌曲名
     * @return
     */
    String sing(String name);
    /**
     * 跳舞
     * @param name 舞曲名
     * @return
     */
    String dance(String name);
}

2). 创建实现Person接口的PersonImpl类

public class PersonImpl implements Person {

    @Override
    public String sing(String name) {
        System.out.println("唱" + name);
        return "唱完了";
    }

    @Override
    public String dance(String name) {
        System.out.println("跳" + name);
        return "不好玩";
    }

}

3). 创建PersonImpl的代理类

public class PersonImplProxy {
    private Person person = new PersonImpl();
    
    public Person createProxy() {
        return (Person) Proxy.newProxyInstance(PersonImplProxy.class.getClassLoader(), person.getClass().getInterfaces(), new InvocationHandler() {
            
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // 编写代码
                return null;
            }
        });
    }
}

4). 编写Demo类中主函数

public class Demo {
    public static void main(String[] args) {
        PersonImplProxy proxy = new PersonImplProxy();
        Person person = proxy.createProxy();
        System.out.println(person.sing("说散就散"));
        System.out.println(person.dance("体面"));
    }
}

5). 实现代理对象中的invoke方法

public class PersonImplProxy {
    private Person person = new PersonImpl();
    
    public Person createProxy() {
        return (Person) Proxy.newProxyInstance(PersonImplProxy.class.getClassLoader(), person.getClass().getInterfaces(), new InvocationHandler() {
            
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // 编写代码
                String methodName = method.getName();
                if ("sing".equals(methodName)) {
                    System.out.println("啦啦啦啦啦啦");
                    return method.invoke(person, args);
                } else if ("dance".equals(methodName)) {
                    System.out.println("哈哈哈哈哈哈");
                    return method.invoke(person, args);
                } else {
                    System.out.println("哈哈哈哈哈哈");
                }
                return null;
            }
        });
    }
}

6). 执行主函数, 打印结果


img_15e3afe1d88be652fda8ab018bfc8ac6.png
图2.png
目录
相关文章
|
4月前
|
缓存 安全 Java
Java中动态代理使用与原理详解
Java中动态代理使用与原理详解
53 0
|
4月前
|
Java
Java之动态代理的详细解析
2. 动态代理 2.1 好处: 无侵入式的给方法增强功能 2.2 动态代理三要素: 1,真正干活的对象
38 0
|
4月前
|
Java
【Java动态代理】—— 每天一点小知识
【Java动态代理】—— 每天一点小知识
|
5月前
|
Arthas Dubbo Java
Alibaba Java诊断工具Arthas查看Dubbo动态代理类
Alibaba Java诊断工具Arthas查看Dubbo动态代理类
53 0
|
1月前
|
Java API 开发者
Java代理模式——静态代理与动态代理
Java代理模式——静态代理与动态代理
26 1
|
1月前
|
监控 Java 程序员
java的动态代理如何实现
java的动态代理如何实现
24 0
|
2月前
|
设计模式 Java 程序员
Java动态代理
Java动态代理详解
|
2月前
|
Java
Java动态代理简易说明
Java动态代理简易说明
10 0
|
2月前
|
设计模式 Java API
[Java]静态代理、动态代理(基于JDK1.8)
本篇文章主要是对静态代理和动态代理实现思路的简述,以示例为主,少涉及理论。 如果文中阐述不全或不对的,多多交流。
54 1
[Java]静态代理、动态代理(基于JDK1.8)
|
3月前
|
设计模式 缓存 Java
Java动态代理:一个面包店的动态代理帝国
Java动态代理:一个面包店的动态代理帝国
31 0