代理模式
1.1 定义:
为其他对象提供一种代理以控制对这个对象的访问。
被代理的对象可以是: 远程对象、创建开销大的对象、需要安全控制的对象
1.2 结构:
1.2.1 角色:
- 抽象主题:对象和它的代理公用的接口
- 实际主题:所要代理的对象
- 代理:含有主题接口声明的变量,用来存放实际主题对象实例的引用。
1.2.2 UML
代理类需要实现被代理的所有非构造方法,且名字一般保持一致,所以一般情况下,会抽象一个接口,使得代理类和被代理类都继承此接口,但是如果代理第三方类库,无法修改第三方类库代码。
1.3 分类:
1.3.1 静态代理:
优点: 在不修改目标对象功能的前提下,通过代理对象对目标功能扩展
缺点: 代理对象需要和目标对象实现一样的接口,所以会有很多代理类
一旦接口增加新方法,目标对象和代理类都要维护
1.3.2 动态代理:
代理类时运行期间生成的,主流有两个实现, 1. java标准库 2. cglib
1.3.2.1 java标准库的实现
需要代理类和被代理类实现同一个接口
// 抽象接口
public interface Geometry {
public double getArea();
}
// 被代理类
public class Triangle implements Geometry{
double sideA, sideB, sideC;
public Triangle(double sideA, double sideB, double sideC) {
this.sideA = sideA;
this.sideB = sideB;
this.sideC = sideC;
}
@Override
public double getArea() {
double p = (sideA + sideB + sideC) / 2.0;
return Math.sqrt(p * (p-sideA) * (p-sideB) * (p-sideC));
}
}
// 中间类
/*需要实现标准库的InvocationHandler接口。
(1)重写构造函数,参数为被代理类,被代理类作为类属性。
(2)实现invoke方法,在这里利用反射调用实际被代理类的方法和添加一些增强的逻辑。*/
public class MethodInvocationCountHandler implements InvocationHandler {
private Object implementation;
public MethodInvocationCountHandler(Object implementation) {
this.implementation = implementation;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行了");
return method.invoke(implementation, args);
}
}
// 调用
public class Client {
public static void main(String[] args) {
Geometry geometry = new Triangle(1, 2, 3);
InvocationHandler invocationHandler = new MethodInvocationCountHandler(geometry);
Geometry geometryProxy = (Geometry) Proxy.newProxyInstance(Geometry.class.getClassLoader(), new Class[]{Geometry.class}, invocationHandler);
geometryProxy.getArea();
}
}
1.3.2.2 cglib (Code Generation Library)
jdk标准库动态代理的实现,需要被代理类实现接口,cglib 不需要, spring aop 中会根据被代理对象是否有实现接口来选择使用jdk 动态代理还是 cglib
// 中间增强类, 需要导入 cglib包, asm包
public class ProxyInterceptor implements MethodInterceptor {
private Object target;
public Object bind(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("执行了");
return methodProxy.invokeSuper(o, objects);
}
}
// 调用
public class Client {
public static void main(String[] args) {
ProxyInterceptor proxyInterceptor = new ProxyInterceptor();
Triangle geometryProxy = (Triangle) proxyInterceptor.bind(new Triangle(1, 2, 3));
geometryProxy.getArea();
}
}