赞
踩
代理模式是一种常用的设计模式,它允许为其他对象提供代理,以控制对这个对象的访问。这种结构在不改变原始类的基础上,通过引入代理类来扩展功能,广泛应用于各种编程场景和框架中。
使用代理前:
使用代理后:
在生活当中也有很多代理模式的例子:
代理模式的主要角色
比如房屋租赁
Subject 就是提前定义了房东做的事情, 交给中介代理, 也是中介要做的事情
RealSubject: 房东
Proxy: 中介
根据代理的创建时期, 代理模式分为静态代理和动态代理.
我们通过代码来加深对静态代理的理解. 以房租租赁为例:
public interface houseSubject {
void rentHouse();
void saleHouse();
}
public class RealHouseSubject implements houseSubject{
@Override
public void rentHouse() {
System.out.println("我是房东,我出租房子");
}
@Override
public void saleHouse() {
System.out.println("我是房东,我出售房子");
}
}
public class HouseProxy implements houseSubject{ private RealHouseSubject target; public HouseProxy(RealHouseSubject realHouseSubject) { this.target = realHouseSubject; } @Override public void rentHouse() { //出租前 System.out.println("我是中介,我开始代理"); //出租房子 target.rentHouse(); //出租后 System.out.println("我是中介,结束代理"); } @Override public void saleHouse() { //出售前 System.out.println("我是中介,我开始代理"); //出售房子 target.saleHouse(); //出售后 System.out.println("我是中介,结束代理"); } }
public class Main {
public static void main(String[] args) {
//创建代理类
HouseProxy houseProxy = new HouseProxy(new RealHouseSubject());
//通过代理类访问目标方法
houseProxy.rentHouse();
}
}
上面这个代理实现方式就是静态代理(仿佛啥也没干). 从上述程序可以看出, 虽然静态代理也完成了对目标对象的代理, 但是由于代码都写死了, 对目标对象的每个方法的增强都是手动完成的,非常不灵活. 所以日常开发几乎看不到静态代理的场景
接下来新增需求: 中介又新增了其他业务, 我们修改接口(Subject)和业务实现类(RealSubject)时, 还需要修改代理类(Proxy). 同样的, 如果有新增接口(Subject)和业务实现类(RealSubject), 也需要对每一个业务实现类新增代理类(Proxy).
动态代理是指我们不需要针对每个目标对象都单独创建一个代理对象, 而是把这个创建代理对象的工作推迟到程序运行时由JVM来实现. 也就是说动态代理在程序运行时, 根据需要动态创建生成.
在Java中实现动态代理的方式主要有两种,一种是JDK动态代理,一种是CGLib. 接下来就主要介绍这两种方式.
public class JDKInvocationHandler implements InvocationHandler { private Object target; //目标对象 public JDKInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("我是代理,开始代理"); //通过反射调用目标函数 Object result = method.invoke(target, args); System.out.println("我是代理,结束代理"); return result; } }
public class Main { public static void main(String[] args) { /** *public static Object newProxyInstance(ClassLoader loader, * Class<?>[] interfaces, * InvocationHandler h) { * 加载代理类的classloader * 要实现的接口, * 代理要做的事情,InvocationHandler这个接口 */ //真实的目标对象 RealHouseSubject targer = new RealHouseSubject(); //动态生成代理对象 houseSubject proxy = (houseSubject)Proxy.newProxyInstance(targer.getClass().getClassLoader(), new Class[]{houseSubject.class}, new JDKInvocationHandler(targer)); proxy.rentHouse(); proxy.saleHouse();
public interface InvocationHandler {
/**
* 参数说明
* proxy:代理对象
* method:代理对象需要实现的⽅法,即其中需要重写的⽅法
* args:method所对应⽅法的参数
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
通过实现 InvocationHandler 接口, 可以对被代理对象的方法进行功能增强.
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException{
//...代码省略
}
public class CGLibMethodInterceptor implements MethodInterceptor { private Object target; public CGLibMethodInterceptor(Object target) { this.target = target; } /** * 调用代理对象的方法 */ @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("我是中介开始代理~~"); Object result = method.invoke(target, args); //proxy.invokeSuper(obj, args); System.out.println("我是中介,结束代理~~"); return result; } }
// 目标对象 代理接口
HouseSubject targer = new RealHouseSubject();
houseSubject houseSubject = (houseSubject) Enhancer.create(targer.getClass(), new CGLibMethodInterceptor(targer));
houseSubject.rentHouse();
houseSubject.saleHouse();
HouseSubject targer = new RealHouseSubject();
//目标对象 代理类
RealHouseSubject realHouseSubject = (RealHouseSubject) Enhancer.create(targer.getClass(), new CGLibMethodInterceptor(targer));
realHouseSubject.rentHouse();
realHouseSubject.saleHouse();
public interface MethodInterceptor extends Callback {
/**
* 参数说明:
* o: 被代理的对象
* method: ⽬标⽅法(被拦截的⽅法, 也就是需要增强的⽅法)
* objects: ⽅法⼊参
* methodProxy: ⽤于调⽤原始⽅法
*/
Object intercept(Object o,
Method method,
Object[] objects,
MethodProxy methodProxy) throws Throwable;
}
public static Object create(Class type, Callback callback) {
//...代码省略
}
protected Object createProxy(Class<?> beanClass,
@Nullable String beanName,
@Nullable Object[] specificInterceptors,
TargetSource targetSource) {
return buildProxy(beanClass, beanName, specificInterceptors, targetSource, false);
}
private Object buildProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource, boolean classOnly) { if (this.beanFactory instanceof ConfigurableListableBeanFactory clbf) { AutoProxyUtils.exposeTargetClass(clbf, beanName, beanClass); } //创建代理对象 ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); /** * 检查proxyTargetClass属性值,spring默认为false * proxyTargetClass 检查接⼝是否对类代理, ⽽不是对接⼝代理 * 如果代理对象为类, 设置为true, 使⽤cglib代理 */ if (proxyFactory.isProxyTargetClass()) { //是否有设置cglib代理 if (Proxy.isProxyClass(beanClass) || ClassUtils.isLambdaClass(beanClass)) { //设置proxyTargetClass为true,使⽤cglib代理 for (Class<?> ifc : beanClass.getInterfaces()) { proxyFactory.addInterface(ifc); } } } else { /** * 如果beanClass实现了接⼝,且接⼝⾄少有⼀个⾃定义⽅法,则使⽤JDK代理 * 否则CGLIB代理(设置ProxyTargetClass为true ) * 即使我们配置了proxyTargetClass=false, 经过这⾥的⼀些判断还是可能会将其 设为true */ if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { evaluateProxyInterfaces(beanClass, proxyFactory); } } Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); proxyFactory.addAdvisors(advisors); proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } // Use original ClassLoader if bean class not locally loaded in overriding class loader ClassLoader classLoader = getProxyClassLoader(); if (classLoader instanceof SmartClassLoader smartClassLoader && classLoader != beanClass.getClassLoader()) { classLoader = smartClassLoader.getOriginalClassLoader(); } return (classOnly ? proxyFactory.getProxyClass(classLoader) : proxyFactory.getProxy(classLoader)); }
注意:
Spring Boot 2.X开始, 默认使用CGLIB代理. 可以通过配置项 spring.aop.proxy-target-class=false 来进行修改,设置默认为jdk代理. SpringBoot设置 @EnableAspectJAutoProxy 无效, 因为Spring Boot 默认使用AopAutoConfiguration进行装配
@SpringBootApplication public class DemoApplication { public static void main(String[] args) { ApplicationContext context = SpringApplication.run(DemoApplication.class, args); /** * HouseProxy houseProxy = context.getBean(HouseProxy.class); * 设置spring.aop.proxy-target-class=true cglib代理, 运⾏成功 * 设置spring.aop.proxy-target-class=false jdk代理, 运⾏失败, 不能代理类 * 因为 HouseProxy 是⼀个类, ⽽不是接⼝, 需要修改为 * HouseSubject houseProxy = (HouseSubject) context.getBean("realHouseSubject") * */ HouseProxy houseProxy = context.getBean(HouseProxy.class); //HouseSubject houseProxy = (HouseSubject) context.getBean("realHouseSubject");//正确运⾏ System.out.println(houseProxy.getClass().toString()); } }
使用context.getBean() 需要添加注解,使HouseProxy,RealHouseSubject被Spring管理测试AOP代理, 需要把这些类交给AOP管理(自定义注解或使用@Aspect)
我看点进去看代理工厂的代码
public class ProxyFactory extends ProxyCreatorSupport { //...代码省略 //获取代理 public Object getProxy(@Nullable ClassLoader classLoader) { //分两步 先createAopProxy,后getProxy return createAopProxy().getProxy(classLoader); } protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } return getAopProxyFactory().createAopProxy(this); } //...代码省略 }
createAopProxy的实现在 DefaultAopProxyFactory中
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable { //...代码省略 @Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { /** * 根据proxyTargetClass判断 * 如果⽬标类是接⼝, 使⽤JDK动态代理 * 否则使⽤cglib动态代理 */ if (!NativeDetector.inNativeImage() && (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } } //...代码省略 }
接下来就是创建代理了
JDK动态代理
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler,
Serializable {
//...代码省略
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " +
this.advised.getTargetSource());
}
return Proxy.newProxyInstance(determineClassLoader(classLoader),
this.proxiedInterfaces, this);
}
//...代码省略
}
CGLIB动态代理
class CglibAopProxy implements AopProxy, Serializable { //...代码省略 @Override public Object getProxy(@Nullable ClassLoader classLoader) { //...代码省略 // Configure CGLIB Enhancer... Enhancer enhancer = createEnhancer(); // Generate the proxy class and create a proxy instance. return createProxyClassAndInstance(enhancer, callbacks); } //...代码省略 }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。