代理模式:为其他对象提供一种代理来控制对该对象的访问。
为了学习动态代理,我们先来学习一下静态代理。一切从实际出发,先看一个小例子。
假设我们有一个Passenger类,它可以自己检查自己的姓名。
public interface Check {
void checkName();
}
public class Passenger implements Check{
private String name;
private String sex;
public void setName(String name){
this.name = name;
}
public void setSex(boolean sex){
this.sex = sex == true ? "男" : "女";
}
@Override
public void checkName() {
System.out.println("自己检查了姓名:"+name+"正确");
}
}
但是现在他自己检查了不算,还需要安检员来检查才行。于是我们这样写:
public class SecurityCheck implements Check{
private Passenger passenger;
public SecurityCheck setPassenger(Passenger passenger){
this.passenger = passenger;
return this;
}
@Override
public void checkName() {
System.out.println("安检员检查通过");
passenger.checkName();
}
}
调用的时候这样:
public static void main(String[] args) {
Passenger pa = new Passenger();
pa.setName("张三");
pa.setSex(true);
new SecurityCheck().setPassenger(pa).checkName();;
}
结果如下:
安检员检查通过
自己检查了姓名:张三正确
看到这里,你会发现一个问题,就是代理类也实现了Check接口,不利于复用和拓展。
动态代理就是解决这个问题的。
代理类:
public class ProxySecurityCheck implements InvocationHandler{
private Object realObject;
public ProxySecurityCheck(Object object){
this.realObject = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 在这里可以做一些操作
System.out.println("提前检查"+method.getName());
return method.invoke(realObject, args);
}
}
使用方法如下:
//被代理类
Passenger passenger = new Passenger();
ProxySecurityCheck psc = new ProxySecurityCheck(passenger);
/**第一个参数:代理类的类加载器
*第二个参数:被代理类的接口
*第三个参数:代理类本身
**/
Check check = (Check)Proxy.newProxyInstance(psc.getClass().getClassLoader(),
passenger.getClass().getInterfaces(),
psc);
check.checkName();
通过对比发现,动态代理和静态代理的区别是:静态代理的代理类有具体的方法,而动态代理的代理类没有具体的方法,那它是怎么实现的呢?
newProxyInstance()方法实际上通过反射创建了一个代理类,生成的这个代理类和上面静态代理方式中的代理类作用差不多,只不过不需要我们自己去实现,由系统帮我们实现罢了。