在学习Spring的AOP部分时,发现我对代理模式尤其是动态代理的了解太少,为了更加透彻的理解写的笔记,如果有写错的地方或者有更好的理解方式欢迎指正
在理解JDK动态代理之前需要先理解一下Java反射
JDK动态代理
我们用一个例子(房屋出租)来理解动态代理:
//被代理类
public class Host implements Rent{
@Override
public void rent() {
System.out.println("租房!");
}
}
//接口
public interface Rent {
public void rent();
}
JDK动态代理主要涉及两个类:java.lang.reflect.Proxy
和 java.lang.reflect.InvocationHandler
-
Proxy
类为代理类,提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类 -
InvocationHandler
为调用逻辑处理器类,这个接口实现的类中维护一个目标对象,这个对象是被代理的对象
public interface InvocationHandler
- InvocationHandler是由代理实例的调用处理程序实现的接口 。
- 每个代理实例都有一个关联的调用处理程序。 当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的invoke方法。
Object invoke(Object proxy,方法 method,Object[] args) throws Throwable
- 处理代理实例上的方法调用并返回结果。 当在与之关联的代理实例上调用方法时,将在调用处理程序中调用此方法。
参数:
proxy - 调用该方法的代理实例
method -所述方法对应于调用代理实例上的接口方法的实例
args -包含的方法调用传递代理实例的参数值的对象的阵列
- 可以理解为额外要加的部分写到
InvocationHandler
重写的invoke
方法中
写我们例子中的调用逻辑处理器类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//这个类生成自动代理类
public class ProxyInvocationhandler implements InvocationHandler {
private Object rent;
public void setRent(Object rent){
this.rent = rent;
}
//处理代理实例,并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//额外加的方法
cry();
Object result = method.invoke(rent, args);
smile();
return result;
}
public void cry(){
System.out.println("Java真难~~~~~~~~");
}
public void smile(){
System.out.println("Java真简单~~~~~~~");
}
}
获取动态生成的代理类的对象须借助 Proxy
类的 newProxyInstance
方法
public class Proxy
Proxy提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。
动态代理类是一个实现在类创建时在运行时指定的接口列表的类
每个代理实例都有一个关联的调用处理程序对象,它实现了接口InvocationHandler
写个测试类:
public static void main(String[] args) {
//真实角色
Host host = new Host();
//代理角色
ProxyInvocationhandler pih = new ProxyInvocationhandler();
pih.setRent(host);
//创建一个代理对象
Rent proxy = (Rent)pih.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
System.out.println("调用rent");
proxy.rent();
}
控制台输出:
调用rent
Java真难~~~~~~~~
租房!
Java真简单~~~~~~~