Spring AOP 源码阅读

Spring AOP 大致流程

Untitled



Spring 代理对象创建流程

java

@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
    ...
}

引入了 AspectJAutoProxyRegistrar.class


在AspectJAutoProxyRegistrar中, 通过在初始化容器实例化对象之前, 回调registerBeanDefinitions()的方法,向BeanDefinition中注册一个 AnnotationAwareAspectJAutoProxyCreator.class

java

@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
	...
	AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
	...
}

Untitled

在上图中我们看到AnnotationAwareAspectJAutoProxyCreator是实现了BeanPostProcessor接口的,

而实现BeanPostProcessor后,当Spring在Bean的初始化后会调用其postProcessAfterInitialization()方法,AOP逻辑由此开始


接着进入postProcessAfterInitialization() 这个方法的逻辑

找到了AnnotationAwareAspectJAutoProxyCreator的父类AbstractAutoProxyCreator 中的这个方法 org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization

java

@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;
}

继续进入方法中wrapIfNecessary()

java

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		// 判断当前bean是否存在匹配的advice, 如果存在则要生成一个代理对象
		// 此处根据类以及类中的方法去匹配到Interceptor(也就是advice). 然后生成代理对象,
		// 代理对象在执行的时候, 还会根据当前执行的方法去匹配
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {

			// advisedBeans记录了某个Bean已经进行过AOP了
			this.advisedBeans.put(cacheKey, Boolean.TRUE);

			// ☆ ->
			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;
	}

继续进入createProxy()方法

java

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}

		// advisedBeans表示已经判断过来的的bean, false表示此bean不需要进行Aop
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}

		// 当前正在创建Bean不用进行AOP, 比如切面Bean
		// shouldSkip() 是模板方法, 子类可以去扩展的
		// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.isInfrastructureClass
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);

			// 直接返回
			return bean;
		}

		// ☆ ->
		// 判断当前bean是否存在匹配的advice, 如果存在则要生成一个代理对象
		// 此处根据类以及类中的方法去匹配到Interceptor(也就是advice). 然后生成代理对象,
		// 代理对象在执行的时候, 还会根据当前执行的方法去匹配
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {

			// advisedBeans记录了某个Bean已经进行过AOP了
			this.advisedBeans.put(cacheKey, Boolean.TRUE);

			// ☆ ->
			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;
	}

该方法做了如下事情:

  1. 进入方法后判断当前Bean是需要进行AOP,advisedBeans相当于是一个缓存,在下面判断过的bean会放入这个map中,避免再次到下面去判断。
  2. 判断当前bean是否存在匹配的advice, 匹配的条件是向根据类名,再根据方法名(如果有必要的话),如果存在则要生成一个代理对象,此处根据类以及类中的方法去匹配到Interceptor(也就是advice). 然后生成代理对象,
  3. 通过 AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors()这个方法找到所有的Advisor

java

@Override
protected List<Advisor> findCandidateAdvisors() {
	// Add all the Spring advisors found according to superclass rules.
	// 找到所有Advisor类型的Bean对象
	List<Advisor> advisors = super.findCandidateAdvisors();

	// Build Advisors for all AspectJ aspects in the bean factory.
	// 再从所有的切面中解析得到Advisor对象
	if (this.aspectJAdvisorsBuilder != null) {

		// 解析AspectJ中定义的切面方法, 并加到advisors中
		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
	}
	return advisors;
}

在该方法中会调用BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors() 把Bean都解析成Advisor, 并在list中返回


buildAspectJAdvisors()代码如下:

BeanFactoryAspectJAdvisorsBuilder.java

public List<Advisor> buildAspectJAdvisors() {
	List<String> aspectNames = this.aspectBeanNames;

	if (aspectNames == null) {
		synchronized (this) {
			aspectNames = this.aspectBeanNames;
			if (aspectNames == null) {
				List<Advisor> advisors = new ArrayList<>();
				aspectNames = new ArrayList<>();
				String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
						this.beanFactory, Object.class, true, false);
				for (String beanName : beanNames) {
					if (!isEligibleBean(beanName)) {
						continue;
					}

					Class<?> beanType = this.beanFactory.getType(beanName, false);
					if (beanType == null) {
						continue;
					}

					// 判断类上是否有AspectJ注解
					if (this.advisorFactory.isAspect(beanType)) {
						aspectNames.add(beanName);

						// 切面的注解信息
						AspectMetadata amd = new AspectMetadata(beanType, beanName);

						// 如果@Aspect不是perthis、pertarget, 那么一个切面只会生成一个对象(单例),
						// 并且会将该切面中的所对应的Advisor对象进行缓存
						if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
							MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
              
              // ☆ ->
							// 利用BeanFactoryAspectInstanceFactory来解析Aspect类
							List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
							if (this.beanFactory.isSingleton(beanName)) {

								// 缓存切面所对应的所有Advisor对象
								this.advisorsCache.put(beanName, classAdvisors);
							} else {
								this.aspectFactoryCache.put(beanName, factory);
							}
							advisors.addAll(classAdvisors);
						} else {
							// Per target or per this.
							if (this.beanFactory.isSingleton(beanName)) {
								throw new IllegalArgumentException("Bean with name '" + beanName + "' is a singleton, but aspect instantiation model is not singleton");
							}
							MetadataAwareAspectInstanceFactory factory = new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
							this.aspectFactoryCache.put(beanName, factory);

							// 利用PrototypeAspectInstanceFactory来解析Aspect类
							// PrototypeAspectInstanceFactory的父类为BeanFactoryAspectInstanceFactory
							// 这两个Factory的区别在于PrototypeAspectInstanceFactory的构造方法中会判断切面Bean是不是原型,
							// 除此之外没有其他区别
							//
							// 所以主要就是BeanFactoryAspectInstanceFactory来负责生成切面实例对象
							advisors.addAll(this.advisorFactory.getAdvisors(factory));
						}
					}
				}
				this.aspectBeanNames = aspectNames;
				return advisors;
			}
		}
	}

	if (aspectNames.isEmpty()) {
		return Collections.emptyList();
	}

	// 如果切面已经找到过了,那么则遍历每个切面是否缓存了对应的Advisor,如果没有缓存则进行解析得到Advisor
	List<Advisor> advisors = new ArrayList<>();
	for (String aspectName : aspectNames) {
		List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
		if (cachedAdvisors != null) {
			advisors.addAll(cachedAdvisors);
		} else {
			MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
			advisors.addAll(this.advisorFactory.getAdvisors(factory));
		}
	}
	return advisors;
}

上面方法中: List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);


java

	@Override
	public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {

    ......

		// 获取切面类中[没有]加@Pointcut的方法,进行遍历生成Advisor, 并排序
		for (Method method : getAdvisorMethods(aspectClass)) {
			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		// 如果是pertarget或perthis,则会多生成一个Advisor并放在最前面
		// 在一个代理对象调用方法的时候,就会执行该Advisor,并且会利用lazySingletonAspectInstanceFactory来生成一个切面Bean
		if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
			advisors.add(0, instantiationAdvisor);
		}

		// 找到哪些字段上加了@DeclareParents注解,把这些字段以及对于的注解解析封装为Advisor,生成代理对象时会把对于的接口添加到ProxyFactory中
		for (Field field : aspectClass.getDeclaredFields()) {
			Advisor advisor = getDeclareParentsAdvisor(field);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		return advisors;
	}

在上面的代码中: getAdvisorMethods(aspectClass) 会获取切面类中没有加@Pointcut的方法,进行遍历生成Advisor, 并排序。


排序规则:

java

static {
	// 先更具下面的注解排序
	Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
			new InstanceComparator<>(
					Around.class,
					Before.class,
					After.class,
					AfterReturning.class,
					AfterThrowing.class
			),
			(Converter<Method, Annotation>) method -> {
				AspectJAnnotation<?> ann = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
				return (ann != null ? ann.getAnnotation() : null);
			});

	// 再根据方法名排序
	Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
	adviceMethodComparator = adviceKindComparator.thenComparing(methodNameComparator);
}

继续回到 Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName); 该方法返回的对象是Advisor的实现类InstantiationModelAwarePointcutAdvisorImpl


InstantiationModelAwarePointcutAdvisorImpl#instantiateAdvice() 方法中会根据方法上的注解生成对应的Advice。

java

// 按不同的注解类型得到不同的Advice
switch (aspectJAnnotation.getAnnotationType()) {
	case AtPointcut:
		if (logger.isDebugEnabled()) {
			logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
		}
		return null;
	case AtAround:
		springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
		break;
	case AtBefore:
		springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
		break;
	case AtAfter:
		springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
		break;
	case AtAfterReturning:
		springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
		AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
		if (StringUtils.hasText(afterReturningAnnotation.returning())) {
			springAdvice.setReturningName(afterReturningAnnotation.returning());
		}
		break;
	case AtAfterThrowing:
		springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
		AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
		if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
			springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
		}
		break;
	default:
		throw new UnsupportedOperationException("Unsupported advice type on method: " + candidateAdviceMethod);
}

各注解对应的MethodInterceptor

  • @Before对应的是AspectJMethodBeforeAdvice,在进行动态代理时会把AspectJMethodBeforeAdvice转成MethodBeforeAdviceInterceptor
    • 先执行advice对应的方法
    • 再执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
  • @After对应的是AspectJAfterAdvice,直接实现了MethodInterceptor
    • 先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
    • 再执行advice对应的方法
  • @Around对应的是AspectJAroundAdvice,直接实现了MethodInterceptor
    • 直接执行advice对应的方法,由@Around自己决定要不要继续往后面调用
  • @AfterThrowing对应的是AspectJAfterThrowingAdvice,直接实现了MethodInterceptor
    • 先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
    • 如果上面抛了Throwable,那么则会执行advice对应的方法
  • @AfterReturning对应的是AspectJAfterReturningAdvice,在进行动态代理时会把AspectJAfterReturningAdvice转成AfterReturningAdviceInterceptor
    • 先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
    • 执行上面的方法后得到最终的方法的返回值
    • 再执行Advice对应的方法

在AspectJ中有五种, 而Spring中只有四种


继续回到 createProxy()方法的 proxyFactory.getProxy(classLoader);

java

	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
		}

		try {
			// 拿到被代理的类
			Class<?> rootClass = this.advised.getTargetClass();
			Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

			Class<?> proxySuperClass = rootClass;
			// 如果被代理的类的本身就已经是在Cglib所生成的代理类了
			if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
				// 获取真正的被代理类
				proxySuperClass = rootClass.getSuperclass();
				// 获取被代理类所实现的接口
				Class<?>[] additionalInterfaces = rootClass.getInterfaces();
				for (Class<?> additionalInterface : additionalInterfaces) {
					this.advised.addInterface(additionalInterface);
				}
			}

			// Validate the class, writing log messages as necessary.
			validateClassIfNecessary(proxySuperClass, classLoader);

			// Configure CGLIB Enhancer...
			Enhancer enhancer = createEnhancer();
			if (classLoader != null) {
				enhancer.setClassLoader(classLoader);
				if (classLoader instanceof SmartClassLoader &&
						((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
					enhancer.setUseCache(false);
				}
			}

			// 被代理类, 代理类的父亲
			enhancer.setSuperclass(proxySuperClass);
			// 代理类额外要实现的接口
			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
			enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));

			// 获取和被代理类所匹配的Advisor
			Callback[] callbacks = getCallbacks(rootClass);
			Class<?>[] types = new Class<?>[callbacks.length];
			for (int x = 0; x < types.length; x++) {
				types[x] = callbacks[x].getClass();
			}
			// fixedInterceptorMap only populated at this point, after getCallbacks call above
			enhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
			enhancer.setCallbackTypes(types);

			// Generate the proxy class and create a proxy instance.
			return createProxyClassAndInstance(enhancer, callbacks);
		} catch (CodeGenerationException | IllegalArgumentException ex) {
			throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
					": Common causes of this problem include using a final class or a non-visible class",
					ex);
		} catch (Throwable ex) {
			// TargetSource.getTarget() failed
			throw new AopConfigException("Unexpected AOP exception", ex);
		}
	}