动态代理机制
- 通过实现 InvocationHandler 接口创建自己的调用处理器
- 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类
- 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型
- 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入
Interface InvocationHandler
该接口中仅定义了一个方法Object:invoke(Object obj,Method method,Object[] args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,args为该方法的参数数组。这个抽象方法在代理类中动态实现。
Proxy
- 该类即为动态代理类
- Protected Proxy(InvocationHandler h) // 构造函数,用于给内部的h赋值
- Static Class getProxyClass (ClassLoader loader,Class[] interfaces) // 获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组
- Static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h) // 返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)
- Dynamic Proxy // 它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些 interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然啦,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。
示例代码
创建抽象主体接口
/**
* @ClassName : Subject
* @Description : 抽象主题接口
* @Author : feng
* @Date: 2020-04-17 19:22
*/
public interface Subject {
void doSomething();
}
创建真实主体接口
/**
* @ClassName : RealSubject
* @Description : 真实主题接口
* @Author : feng
* @Date: 2020-04-17 19:23
*/
public class RealSubject implements Subject {
public void doSomething() {
System.out.println("RealSubject do something");
}
}
实现InvocationHandler
/**
* @ClassName : JdkProxy
* @Description : jdk动态代理
* @Author : feng
* @Date: 2020-04-17 09:05
*/
public class JdkProxy implements InvocationHandler {
private Object target;
public JdkProxy(Object target){
this.target = target;
}
/**
* 获取被代理接口实例对象
* @param <T>
* @return
*/
public <T> T getProxy() {
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result = method.invoke(target, args);
after();
return result;
}
private void before(){
System.out.println("Do something before");
}
private void after(){
System.out.println("Do something after");
}
}
测试类
public class JdkProxyTest {
public static void main(String[] args) {
Subject subject = new JdkProxy(new RealSubject()).getProxy();
subject.doSomething();
}
}
运行结果
Do something before
RealSubject do something
Do something after