继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

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

艾贺521
关注TA
已关注
手记 292
粉丝 1.1万
获赞 1544

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

https://img1.mukewang.com/5be948e300014a7410000658.jpg

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,实现的接口,实现接口的类

参考:


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP