代理模式(Proxy Pattern)__浅谈与装饰器模式的区别
代理模式(英语:Proxy Pattern):为其他对象提供一种代理以控制对这个对象的访问。
代理模式和装饰器模式的共同点:
不改变原有组件的情况下增强其功能
代理模式和装饰器模式的差异:
代理模式可以实现延迟加载,即在需要时才真正创建原有组件,而不是在创建代理时就立即创建原有组件,这对于提高性能和节省资源是有益的。(延迟加载)
代理模式更着重于环绕组件的方式(代理行为)的附加动作,装饰器模式则是在组件基础上做固有拓展(自身行为)。
代理模式适用于更灵活、更复杂、更抽象的功能增强场景,装饰器模式适用于直接简洁的功能增强场景。
代码演示(Java)
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class ProxyFactory implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = proxy.invokeSuper(obj, args);
long endTime = System.currentTimeMillis();
long elapsedTime = endTime - startTime;
System.out.println("Method " + method.getName() + " execution time: " + elapsedTime + " ms");
return result;
}
}
// ------------------------------
public class Cat {
public void meow(){
System.out.println("meow~~~meow~~~");
}
}
// ------------------------------
import org.ashe.demo.domain.Cat;
import org.ashe.demo.proxy.ProxyFactory;
import org.springframework.cglib.proxy.Enhancer;
public class Ashe {
public static void main(String[] args) {
// 创建Enhancer对象
Enhancer enhancer = new Enhancer();
// 设置被代理类的类对象
enhancer.setSuperclass(Cat.class);
// 设置回调函数
enhancer.setCallback(new ProxyFactory());
// 创建代理对象
Cat proxy = (Cat) enhancer.create();
// 调用代理对象的方法
proxy.meow();
}
}
以上代理使用CGLIB动态代理实现了对Cat对象meow方法的监控,记录了meow方法的执行耗时时间。且可以看出enhancer.create()
方法执行时,代理对象poxy
才会生成,体现了其延迟加载的特性。
值得注意的是被动态代理后,代理对象的所有行为都会被代理,因此给Cat类增加新方法时,代理对象的新方法也会被监控执行耗时。
为什么要代理分为静态代理和动态代理?
-
减少重复代码: 动态代理可以在运行时动态地生成代理对象,不需要手动编写大量的代理类,从而减少了代码量。
-
灵活性: 动态代理可以代理任意接口或类,不需要为每个被代理的类或接口编写一个对应的代理类,提高了系统的灵活性。
-
适应性: 动态代理可以适应接口或类的变化,不需要修改代理类的代码。这种松耦合性使得系统更容易维护和扩展。
讨论CGLIB动态代理时,就很容易联想到AOP(面向切面编程),其实Spring AOP实现就是基于代理模式(JDK动态代理+ CGLIB 动态代理),因此在使用Spring AOP切面编程的时候,其实是比较厚重的,因为它对整个Controller做了代理,因此IOC中存在
代理Controller
对象和原生Controller
对象两份实例,因此在应用简单场景的切面编程时,从降低复杂度出发,可以优先考虑代理模式等其他更简洁的方案。