🍃前言
前面的博客中,博主对代理模式进行了一个简单的讲解,接下来博主将对Spring AOP源码进行简单剖析,使我们对Spring AOP了解的更加深刻。
🍀Spring AOP源码剖析
Spring AOP 主要基于两种⽅式实现的:JDK 及 CGLIB 的⽅式
Spring对于AOP的实现,基本上都是靠AnnotationAwareAspectJAutoProxyCreator 去完成⽣成代理对象的逻辑在⽗类 AbstractAutoProxyCreator 中
相关源码与注解如下:
protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) { AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); } //创建代理⼯⼚ ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); /** * 检查proxyTargetClass属性值,spring默认为false * proxyTargetClass 检查接⼝是否对类代理, ⽽不是对接⼝代理 * 如果代理对象为类, 设置为true, 使⽤cglib代理 */ if (!proxyFactory.isProxyTargetClass()) { //是否有设置cglib代理 if (shouldProxyTargetClass(beanClass, beanName)) { //设置proxyTargetClass为true,使⽤cglib代理 proxyFactory.setProxyTargetClass(true); } else { /** * 如果beanClass实现了接⼝,且接⼝⾄少有⼀个⾃定义⽅法,则使⽤JDK代理 * 否则CGLIB代理(设置ProxyTargetClass为true ) * 即使我们配置了proxyTargetClass=false, 经过这⾥的⼀些判断还是可能会将其 设为true */ 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 && classLoader != beanClass.getClassLoader()) { classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader(); } //从代理⼯⼚中获取代理 return proxyFactory.getProxy(classLoader); }
代理工⼚有⼀个重要的属性:proxyTargetClass,默认值为false.
也可以通过程序设置
proxyTargetClass | ⽬标对象 | 代理⽅式 |
false | 实现了接⼝ | jdk代理 |
false | 未实现接⼝(只有实现类) | cglib代理 |
true | 实现了接⼝ | cglib代理 |
true | 未实现接⼝(只有实现类) | cglib代理 |
可以通过 @EnableAspectJAutoProxy(proxyTargetClass = true) 来设置
需要注意的是:
- 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); } //...代码省略 }
以上就是对Spring AOP源码的一个简单剖析。
⭕总结
关于《【JavaEE进阶】 Spring AOP源码简单剖析》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下