Java中的静态代理、JDK动态代理和CGLIB动态代理(2)

在Java的JDK动态代理中,主要涉及两个类,一个是java.lang.reflect.Proxy,一个是java.lang.reflectInvocationHandler。要使用JDK的动态代理需要一个实现InvocationHandler接口的中间类,这个接口只有一个方法invoke()方法,对处理类的所有方法的调用都会变成对invoke()方法的调用,这样就可以在invoke()方法中添加统一的处理逻辑(也可以根据method参数判断是哪个方法)。中间类(实现了InvocationHandler的类)有一个委托类对象引用,在invoke()方法中调用了委托类对象的相应方法,通过这种聚合的方式持有委托类对象引用,把外部对invoke()方法的调用最终都转为对委托类对象的调用。

实际上,中间类与委托类构成了静态代理关系,在这个关系中,中间类是代理类,委托类是委托类。然后代理类与中间类也构成一个静态代理关系,在这个关系中,中间类是委托类,代理类是代理类。也就是说,动态代理关系是由两组静态代理关系组成的,这就是JDK动态代理的原理。

InvocationHandler接口的定义源码与参数说明(在注释中)

public interface InvocationHandler {
    /**
    * 调用处理
    * @param proxy 代理类对象
    * @param methon 标识具体调用的是代理类的哪个方法
    * @param args 代理类方法的参数
    */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

定义接口和接口的实现类

// 委托类接口
public interface HelloService {
    void sayHello(String userName);

void sayByeBye(String userName);
}

// 委托类
public class HelloServiceImpl implements HelloService {
    public void sayHello(String userName) {
        System.out.println("hello, " + userName);
    }

public void sayByeBye(String userName) {
        System.out.println("byebye, "+ userName);
    }
}

定义一个实现InvocationHandler接口的中间类

// 中间类
public class HelloInvocationHandler implements InvocationHandler {
    /**
    * 中间类持有委托类对象的引用,这里会构成一种静态代理关系
    */
    private Object obj;

/**
    * 有参构造器,传入委托类的对象
    *
    * @param obj 委托类的对象
    */
    public HelloInvocationHandler(Object obj) {
        this.obj = obj;
    }

/**
    * 动态生成代理类对象,Proxy.newProxyInstance
    *
    * @return 返回代理类的实例
    */
    public Object newProxyInstance() {
        return Proxy.newProxyInstance(
                // 指定代理对象的类加载器
                obj.getClass().getClassLoader(),
                // 代理对象需要实现的接口,可以同时指定多个接口
                obj.getClass().getInterfaces(),
                // 方法调用的实际处理者,代理对象的方法调用都会转发到这里
                this);
    }

/**
    * @param proxy  代理对象
    * @param method 代理方法
    * @param args  方法的参数
    */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在invoke前做一些事情
        System.out.println("do something before invoke...");
        // 执行invoke
        Object result = method.invoke(obj, args);
        // 在invoke之后做一些事情
        System.out.println("do something after invoke...");

return result;
    }
}

通过中间类访问委托类

// 测试动态代理类
public class HelloTest {
    public static void main(String[] args) {
        HelloInvocationHandler helloInvocationHandler = new HelloInvocationHandler(new HelloServiceImpl());
        HelloService helloService = (HelloService) helloInvocationHandler.newProxyInstance();
        helloService.sayHello("yanggb");
        helloService.sayByeBye("yanggb");
    }
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/24809789f1cfabf8c6f7da24a50869d5.html