为什么要采用代理模式呢?代理模式有什么用处与功能?
对于创建的一个类对象,我们在使用该对象的时候,经常需要添加一些操作,例如每次执行对象的方法的时候,我们想验证参数或者做一些日志记录。那么,在不修改原来类的基础上,就需要代理模式进行实现了。原来的类可称为被代理类,我们自己新建的类叫做代理类。
代理类需要将被代理类包含进来,作为自己的一个属性成员,以便在代理类中通过这个属性成员调用被代理类的方法。注意,代理类是不需要添加新的方法的,方法都是通过调用属性成员被代理类对象的的方法。
一般都是通过实现接口的方式,来实现代理类,如图,使用静态代理时,一般一个接口就要对应一个代理类。
代理分为静态代理和动态代理:
静态代理
静态代理的特征是:代理类和目标对象的类都在编译期间确定下来,不利于程序的扩展。
同时,每一个代理类只能为一个接口服务,这样一来,程序开发中必然产生过多的代理。
静态代理需要手动的建立与被代理中的方法对应关系,一般是被代理类中有哪些方法,代理类就需要写出这些方法,并调用被代理类对象的方法。
接口:
public interface ClothFactory {
public void produceCloth();
public void colorCloth();
}
被代理类:
public class NackClothFactory implements ClothFactory{
@Override
public void produceCloth() {
System.out.println("produceCloth");
}
@Override
public void colorCloth() {
System.out.println("colorCloth");
}
}
静态代理类:
public class ClothFactoryProxy implements ClothFactory{
//将被代理类对象作为代理类的成员属性
ClothFactory clothFactory;
public ClothFactoryProxy(ClothFactory clothFactory) {
this.clothFactory = clothFactory;
}
@Override
public void produceCloth() {
clothFactory.produceCloth();
}
@Override
public void colorCloth() {
clothFactory.colorCloth();
}
}
在使用时,就需要创建被代理类对象,并初始化代理类的成员属性,使用时,使用代理类。
@Test
public void NackProxy(){
NackClothFactory nackClothFactory = new NackClothFactory();
ClothFactoryProxy clothFactoryProxy = new ClothFactoryProxy(nackClothFactory);
clothFactoryProxy.produceCloth();
clothFactoryProxy.colorCloth();
}
静态代理需要实现被代理类的每个方法,而且对于不同的接口的实现类,需要创建不同的代理类。
当需要在每个方法里添加相同的操作,如检验参数,增加日志,那么使用静态代理模式,代码繁杂和冗余。
此时就需要用动态代理来解决。
动态代理
动态代理类,可以为不同的接口实现服务
主要使用到InvocationHandler 接口 和 Proxy类的newProxyInstance方法,
1.创建一个实现了InvocationHandler接口的实现类
2.在该类中,创建目标类对象作为成员:Object obj;
3.通过函数初始化目标对象obj,并使用newProxyInstance方法返回目标类的代理类
4.在invoke方法中,调用目标类的函数,并返回值。
public class MyInvocationHandler implements InvocationHandler {
<span style="white-space:pre"> </span>//1.创建目标对象,作为成员
Object obj;
//2.初始化被代理类对象,
//3.并使用Proxy的静态方法newProxyInstance方法根据具体的目标对象创建代理类对象
public Object blind(Object obj) {
this.obj = obj;
//newProxyInstance会调用的第三个参数,就是代理对象本身
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
}
//4.调用代理类对象的方法时,会主动调用到该invoke方法
//其中,Method对象和Object[]就是利用反射机制调用方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//调用被代理对象的对应方法
Object result = method.invoke(obj, args);
return result;
}
}
使用:
@Test
public void DynimicProxy(){
//1.创建被代理类的对象
NackClothFactory nackClothFactory = new NackClothFactory();
//2.创建一个实现了InvocatinHandler接口的类对象
MyInvocationHandler handler = new MyInvocationHandler();
//3.调用blind方法,动态获取代理类对象
ClothFactory proxy = (ClothFactory) handler.blind(nackClothFactory);
proxy.produceCloth();
proxy.colorCloth();
}