Java使用Porxy和InvocationHandler实现动态代理

代理模式:通过代理间接的调用被代理对象的方法,结构如下:

image.png

Java的反射包提供了一个Porxy类和InvokationHandler接口。它们结合在一起后可以创建动态代理类。Porxy类基于传递的参数创建动态代理类。InvokationHandler则用于激发动态代理类的方法。这个过程是在程序执行过程中动态生成与处理的,所以叫动态代理。分析一下

Porxy类

Porxy类提供了一个静态方法创建动态代理类。

public static Object newProxyInstance(ClassLoader loader,           
    Class<?>[] interfaces,                                      
    InvocationHandler h)
throws IllegalArgumentException

1、ClassLoader:ClassLoader会定义动态代理类,ClassLoader可以通过类或者接口获得,如果我们想通过接口获得,调用方法如下。

    Task.class.getClassLoader()

如果通过类来获得,加入我们有一个类TaskImpl实现了Task接口,我们有个TaskImpl的对象ob,然后ClassLoader获取方法如下

    ob.getClassLoader()

2、 Class<?>[] interfaces:动态代理类需要实现的接口
3、InvocationHandler:传递一个实现了InvokationHandler接口的类的实例

InvokationHandler

InvokationHandler是Java 反射包里面的一个接口。InvokationHandler通过用户类来实现,来激发一个动态代理类的方法。它只有一个方法:

public Object invoke(Object proxy, Method method, Object[] args)    throws Throwable;

1、Object:实现方法的代理对象
2、Method:代理实例激发的方法,Porxy参数中的接口方法
3、Object[]:传递给方法的一系列参数

实现

1、我们提供一个接口

package me.aihe;

public interface Task {
    void setData(String data);
    int getCalData(int x);
}

2、实现这个接口

package me.aihe;

public class TaskImpl implements Task {
    @Override
    public void setData(String data) {
        System.out.println(data+ " Data is saved");
    }

    @Override
    public int getCalData(int x) {
        return x * 10;
    }
}

3、定义自己的InvokationHandler类,并且实现InvokationHandler接口的Invoke方法

package me.aihe;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class MyInvokationHandler implements InvocationHandler {

    private Object obj;
    public MyInvokationHandler(Object object){
        this.obj = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result;
        if(method.getName().contains("get")){
            System.out.println("...get Method Executing...");
        }else{
            System.out.println("...set Method Executing...");
        }
        result = method.invoke(obj, args);
        return result;
    }
}

4、创建一个工厂类获取动态代理类:

package me.aihe;

import java.lang.reflect.Proxy;

public class ProxyFactory {
    public static Object newInstance(Object ob) {
        return Proxy.newProxyInstance(ob.getClass().getClassLoader(),
                new Class<?>[] { Task.class }, new MyInvokationHandler(ob));
    }
}

5、提供我们的测试类

package me.aihe;

public class Test {

    public static void main(String[] args) {
        Task task = (Task)ProxyFactory.newInstance(new TaskImpl());
        task.setData("Test");
        System.out.println("============");
        System.out.println(task.getCalData(5));
    }
}

看到程序的输出结果:

...set Method Executing...
Test Data is saved
============
...get Method Executing...
50

总结

动态代理的实现流程:
1、创建一个接口
2、提供一个实现这个接口的类
3、创建一个实现了InvokationHandler接口的类,实现Invoke方法。
传递参数:实现接口的类
4、可选:创建一个代理工厂。
返回值传递参数:ClassLoader,实现的接口,实现接口的类

参考:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Java代理和动态代理机制分析和应用 概述 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个...
    丸_子阅读 8,178评论 6 57
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,828评论 19 139
  • 风在耳边飞, 人在路上醉。 自由天空下, 潇洒跑一回。
    天下有双_a7de阅读 1,054评论 0 0
  • 昨晚其实心情不好,由同事的被离职,想到了很多,就是比较擅长瞎想的! 想去做的事可能和大多数人不符合,家人多半也不会...
    bobo啊bobo阅读 1,432评论 0 2
  • 愤怒一词,听起来是极其消极的,如果我们听说某人常常表现出愤怒,一定觉得此人太糟糕,要敬而远之。实际上愤怒代表着攻击...
    晴妈小时空阅读 3,715评论 0 0

友情链接更多精彩内容