代理模式
定义
代理模式指为其他对象提供一种代理,以控制对这个对象的访问,属于结构型设计模式
在某些情况下,一个对象不适合或不能直接引用另一个对象,而代理对象可以在客户端与目标对象之间起到中介的作用,使用代理模式可以保护目标对象或者增强目标对象。常用在事务代理、日志监听、缓存、远程调用等场景。代理模式和适配器模式之间的主要区别在于代理模式提供了完全相同的接口,装饰器模式增强了接口,适配器模式更改了接口。
类图 -静态代理
JDK-动态代理
JDK动态代理核心是Java.lang.reflect.InvovationHandler接口,要使用动态代理就必须实现该接口。
实现-InvacationHandler,动态代理核心的步骤
public class TargetPorxy implements InvocationHandler {
private Target target;
public TargetPorxy(Target target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
method.invoke(target,args)
after();
return null;
}
private void before(){
System.out.println("执行之前调用");
}
private void after(){
System.out.println("执行之后调用");
}
}
public class JdkDynamicProxy {
public static void main(String[] args) {
final Target target = (Target) Proxy.newProxyInstance(Target.class.getClassLoader(), new Class[]{Target.class}, new TargetPorxy(new TargetImpl()));
target.sayHello();
}
CGLib-动态代理
public class CglibProxy implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before();
methodProxy.invokeSuper(o,objects);
after();
return null;
}
private void before(){
}
private void after(){}
}
public class CglibProxyClient {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(TargetImpl.class);
enhancer.setCallback(new CglibProxy());
final TargetImpl o = (TargetImpl) enhancer.create();
o.sayHello();
}
}
JDK动态代理实现了被代理对象的接口,** CGLib动态代理继承了被代理对象**( enhancer.setSuperclass(TargetImpl.class))。两者均在运行期生成字节码,JDK动态代理直接写Class字节码,CGLib动态代理使用ASM框架写Class字节码。JDK动态代理调用代理方法是通过反射机制调用的,CGLib动态代理是通过FastClass机制直接调用方法的,CGLib动态代理的执行效率更高
开源框架的使用
-
spring中的使用,关注ProxyFactoryBean类
package org.springframework.aop.framework; public class ProxyFactoryBean extends ProxyCreatorSupport implements FactoryBean<Object>, BeanClassLoaderAware, BeanFactoryAware { @Nullable public Object getObject() throws BeansException { this.initializeAdvisorChain(); if (this.isSingleton()) { return this.getSingletonInstance(); } else { if (this.targetName == null) { this.logger.info("Using non-singleton proxies with singleton targets is often undesirable. Enable prototype proxies by setting the 'targetName' property."); } return this.newPrototypeInstance(); } } } private synchronized Object getSingletonInstance() { if (this.singletonInstance == null) { this.targetSource = this.freshTargetSource(); if (this.autodetectInterfaces && this.getProxiedInterfaces().length == 0 && !this.isProxyTargetClass()) { Class<?> targetClass = this.getTargetClass(); if (targetClass == null) { throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy"); } this.setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader)); } super.setFrozen(this.freezeProxy); this.singletonInstance = this.getProxy(this.createAopProxy());//或得代理对象,会根据被代理类的特点选择是JDK动态代理还是CGLib动态代理 } return this.singletonInstance; }