本文基于 SpringBoot5.1.8.RELEASE 版本源码解析
Spring IOC源码解析(1)
Spring IOC源码解析(2)
Spring拓展点及调用顺序总结
我们直接通过SpringBoot项目来调试,建议阅读此文前先熟悉 Spring IOC源码,对SpringBoot自动装配有了解。
目录
0. 概念简述
- PointCut:定义了哪些方法需要被增强,或者说需要被拦截,切点。
- Advice:拦截后的方法具体需要做什么操作(@Before,@Around,@After做些什么事情)。
- Advisor:内部包含了PointCut属性和Advice属性的。
1. AnnotationAwareAspectJAutoProxyCreator
我们先看看这个关键类AnnotationAwareAspectJAutoProxyCreator的继承关系图。
最左上角,我们可以看到熟悉的BeanPostProcessor。
在此我们可以大致猜测到SpringAop也是在Bean初始化后返回一个代理对象。
2. AnnotationAwareAspectJAutoProxyCreator的注册
SpringBoot中使用自动装配的方式。我们可以看看spring-boot-autoconfigure-2.1.6.RELEASE.jar中org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
-
AopAutoConfiguration
@Configuration @ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class, AnnotatedElement.class }) @ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true) public class AopAutoConfiguration { //默认实现cglib方式,注册该bean @Configuration //我们进去看看@EnableAspectJAutoProxy @EnableAspectJAutoProxy(proxyTargetClass = true) @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true) public static class CglibAutoProxyConfiguration { } }
-
@EnableAspectJAutoProxy
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented //看看AspectJAutoProxyRegistrar @Import(AspectJAutoProxyRegistrar.class) public @interface EnableAspectJAutoProxy { }
-
AspectJAutoProxyRegistrar
//我们直接跟踪进去这行,看到AopConfigUtils注册了AnnotationAwareAspectJAutoProxyCreator.class AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
3. AOP源码解析
通过上面我们知道了AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessor,同时也继承了InstantiationAwareBeanPostProcessor。
创建Bean的时候会调用先调用InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation和InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation;
再调用BeanPostProcessor.postProcessBeforeInitialization和BeanPostProcessor.postProcessAfterInitialization.
我们发现InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation和BeanPostProcessor.postProcessAfterInitialization有对应逻辑。而BeanPostProcessor.postProcessAfterInitialization包含InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation逻辑。所以我们就只看BeanPostProcessor.postProcessAfterInitialization。
3.1. AbstractAutoProxyCreator
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
//如果需要代理,则进行以下逻辑
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//3.1.1 判断是否aop相关的(Advice、PointCut、Advisor、AopInfrastructureBean)类,这些类无需增强,调用的是子类AnnotationAwareAspectJAutoProxyCreator.isInfrastructureClass
//判断是不是应该跳过 (AOP解析直接解析出我们的切面信息(并且把我们的切面信息进行缓存),我们先不跟进去
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
//返回匹配当前bean的所有advisor、advice、interceptor。也就是不管你使用的@Before,@After等方式都会返回一个,按照顺序形成一个调用链
//3.1.2:1、获取所有advisor。2、把tagClass所有的方法都解析出来。3、通过advisor中的pointCut拦截点匹配方法判断是否是切点。4、如果是切点,返回该advisor
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
/:3.1.3:创建代理对象,我们进去看看
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
//3.1.1: 判断是否(Advice、PointCut、Advisor、AopInfrastructureBean)类
protected boolean isInfrastructureClass(Class<?> beanClass) {
boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
Pointcut.class.isAssignableFrom(beanClass) ||
Advisor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass);
return retVal;
}
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
//省略代码...
// 3.1.3: 直接看获取代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}
3.1.1. AnnotationAwareAspectJAutoProxyCreator.isInfrastructureClass
@Override
protected boolean isInfrastructureClass(Class<?> beanClass) {
// 是否aop相关的(Advice、PointCut、Advisor、AopInfrastructureBean)类,这些类无需增强(调用父类,就是上面的AbstractAutoProxyCreator.isInfrastructureClass)
// 判断是否有@Aspect注解
return (super.isInfrastructureClass(beanClass) ||
(this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
}
3.1.2. AbstractAdvisorAutoProxyCreator
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//从BeanFactory中获取所有合格的Advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//遍历所有的Advisor,遍历目标类所有的方法,判断Advisor中定义的pointCut是否应用于改方法,返回对应的Advisor
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
3.1.3. ProxyFactory.getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
//我们先看看createAopProxy()这个方法,最终最终跟踪到如下方法类3。再看看getProxy,就是获取代理对象
return createAopProxy().getProxy(classLoader);
}
3.1.4. AbstractAutoProxyCreator.createProxy
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
//建立一个ProxyFactory,把Advisor设置进去,把代理目标类targetSource设置进去
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//通过这个工厂创建代理类
return proxyFactory.getProxy(getProxyClassLoader());
}
3.1.5. DefaultAopProxyFactory.createAopProxy
//此处的AdvisedSupport config就是包含代理目标类的所有Advisors的一个对象
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//判断返回使用JdkDynamicAopProxy还是ObjenesisCglibAopProxy方式代理
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException();
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
3.1.6. 以上返回了proxy代理对象,执行的时候就调用相应的invoke方法,我们看看JdkDynamicAopProxy。
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//代理目标类
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
//获取所有代理对象的拦截对象Advice,就是通过我们上面的ProxyFactory工厂设置进去的
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
//通过责任链模式调用
retVal = invocation.proceed();
return retVal;
}
}
4. 总结一下
- 启动时注册AnnotationAwareAspectJAutoProxyCreator,这是一个BeaPostProcessor,初始化时候会调用该类postProcessAfterInitialization方法进行包装返回代理类
- 初始化时:对需要进行代理的类,进行处理,获取该bean的Advisor,匹配bean里面的所有方法,是否需要代理。然后再返回所有Advisor/Advice/Intecepter拦截对象,组成一个数组,设置到proxyFactory中,通过proxyFactory创建对应的jdk或cglib代理类。
- 执行调用时,调用相应的代理类,并通过责任链模式调用bean所有Advice拦截对象处理相应代理逻辑。
- 本文简单的介绍了一下基础逻辑,详细代码有兴趣可以自行去阅读。