前述
代理模式(Proxy)是一个重要的设计模式,提供了对目标对象另外的访问方式(即通过代理来访问对象)。
举例:我们可以理解为代理权,如各大药材公司生产的药品,一般不会是公司自己零散售出,在个体病人与生产商之间会有一个代理商,代理商负责与公司沟通批量购入,然后再零散出售给病人,因而病人想要访问生产商需先与代理商沟通。也可以考虑(NBA球星——经纪人——球队)三者的关系;
优势:
(1)可以在目标对象实现的基础上,增加额外的功能操作(扩展目标对象的功能);
(2)职责更加清楚,更加智能化;
代理模式的关键在于:代理对象和目标对象;
一般分为动态代理和静态代理。
静态代理
条件:代理对象需是实现与目标对象一样的的接口
优点:可以做到在不修改目标对象功能的前提下,对目标对象的功能进行扩展;
缺点:
(1)代理对象与目标对象接口一致,导致所实行的类过于繁多。
(2)一旦接口增加方法,目标对象和代理对象都需要实现与维护。
动态代理
(1)代理对象不需要实现接口
(2)包含JDK代理、CGLIB代理
- JDK代理
JDK中生成代理的API:
proxy:被代理的类的实例
method:调用被代理的类的方法
args:该方法需要的参数
public Object getProxyInstance() {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),目标对象的类加载器
target.getClass().getInterfaces(),目标对象的接口
new InvocationHandler() {//事件处理器
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//执行目标对象的方法
Object returnValue = method.invoke(proxy, args);
return returnValue;
}
});
}
}
//在main函数中调用该方法(getProxyInstance())
- CGLIB代理
Cglib是一个字节码增强库,该代理对象的实现是在字节码的层面上。
实现步骤:
(1)实现MethodInterceptor接口,重写intercept方法(拦截器)
(2)写一个目标类的代理实现方法getInstance,设置Enhance工具类,设置父类回调函数,创建子类操作;
public class FactoryProxy implements MethodInterceptor {
//维护一个目标对象
private Object target;
public FactoryProxy(Object target) {
this.target = target;
}
//设置代理类
public Object getInstance() {
//设置工具类
Enhancer enhancer = new Enhancer();
//设置父类
enhancer.setSuperclass(target.getClass());
//回调函数
enhancer.setCallback(this);
//创建子类(代理类)
return enhancer.create();
}
//拦截器
@Override
public Object intercept(Object arg0, Method method, Object[] arg2, MethodProxy arg3) throws Throwable {
//执行目标对象的方法
Object returnValue = method.invoke(target, arg2);
return returnValue;
}
}
注意:
(1)目标对象的类不能为final
(2)目标方法如果为static、final,那么将不会执行拦截操作;