Spring之AOP源码解析

aop涉及的核心类如下:

在这里插入图片描述

以上所有类都是aop包下的类。并且AbstractAutoProxyCreator实现了接口SmartInstantiationAwareBeanPostProcessor及其父类InstantiationAwareBeanPostProcessor、BeanPostProcessor并且实现了这仨接口的所有方法。

  1. BeanNameAutoProxyCreator:基于Bean配置名规则的自动代理生成器:允许为一组特定配置名的Bean自动创建代理实例的代理创建器。
  2. DefaultAdvisorAutoProxyCreator:基于Advisor匹配机制的自动代理创建器它会对容器中的所有Advisor进行扫描,自动将这些切面应用到匹配的Bean中。
  3. AbstractAdvisorAutoProxyCreator:基于Bean中AspectJ注解的自动代理生成器:为包含AspectJ注解的切入的Bean自动创建代理实例。

AspectJAwareAdvisorAutoProxyCreator它用于xml配置版的AspectJ切面自动代理创建(aop:config)。
AnnotationAwareAspectJAutoProxyCreator用于基于注解的自动代理创建(aop:aspectj-autoproxy 或 @EnableAspectJAutoProxy)。

跟事务相关的AbstractAutoProxyCreator之InfrastructureAdvisorAutoProxyCreator:利用ImportBeanDefinitionRegistrar接口的子类AutoProxyRegistrar实现的。AutoProxyRegistrar是通过@EnableTransactionManagement之TransactionManagementConfigurationSelector间接实现的。在TransactionAutoConfiguration类中开始初始化的。

跟AspectJ切面相关的AnnotationAwareAspectJAutoProxyCreator:利用ImportBeanDefinitionRegistrar接口的子类AspectJAutoProxyRegistrar实现的。AspectJAutoProxyRegistrar是通过@EnableAspectJAutoProxy实现的。在AopAutoConfiguration类中开始初始化。

1、注解EnableAspectJAutoProxy

该注解「spring-context包下」已经被自动装配类AopAutoConfiguration取代「spring-boot-autoconfigure包下」。

@Configuration
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class, AnnotatedElement.class })
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {

	// spring.aop.proxy-target-class=false 并且被代理类实现了接口,则启动JDK代理。其余均是cglib代理。
	@Configuration
	@EnableAspectJAutoProxy(proxyTargetClass = false)
	@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",
			matchIfMissing = false)
	public static class JdkDynamicAutoProxyConfiguration {

	}

	@Configuration
	@EnableAspectJAutoProxy(proxyTargetClass = true)
	@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
			matchIfMissing = true)
	public static class CglibAutoProxyConfiguration {

	}

}

该注解的主要作用是注册bean~AnnotationAwareAspectJAutoProxyCreator

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
		BeanDefinitionRegistry registry, @Nullable Object source) {

	return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

通过模板模式:AnnotationAwareAspectJAutoProxyCreatord 的父类AbstractAutoProxyCreator 实现了 BeanPostProcessor 接口的方法。也是实现代理的重要类。

2、切面类之IOC容器

IOC容器中涉及的切面类以及其通过属性Autowired注解引入的依赖都不会生成代理类。切点标识的切入类会以代理方式生成bean。

切入类的代理并非 IOC中步骤#4.3生成方式

2.1、AspectJAwareAdvisorAutoProxyCreator后置处理器

涉及文章中步骤4.1.1后置处理器。最终会调用到抽象类AbstractAutoProxyCreator#postProcessBeforeInstantiation

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
	Object cacheKey = getCacheKey(beanClass, beanName);
	if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
		if (this.advisedBeans.containsKey(cacheKey)) {
			return null;
		}
		if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
			// 在Spring实例化切面类的过程中,当前切面类beanClass在集合中持有
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return null;
		}
	}
	TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
	if (targetSource != null) {
		if (StringUtils.hasLength(beanName)) {
			this.targetSourcedBeans.add(beanName);
		}
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
		Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
		this.proxyTypes.put(cacheKey, proxy.getClass());
		return proxy;
	}
	return null;
}

对于普通bean以及切点标识的切入类最终都会返回null。切面类会添加到集合advisedBeans中。

2.2、AnnotationAwareAspectJAutoProxyCreator后置处理器

文章步骤#4.5.1中触发该后置处理器的postProcessAfterInitialization方法。最终都会调用到抽象类AbstractAutoProxyCreator#postProcessAfterInitialization

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;
	}
	// 判断是否是基础类:是否实现接口Advice、Pointcut、Advisor、AopInfrastructureBean等接口「Advice.class.isAssignableFrom(beanClass)」
	// AspectJAwareAdvisorAutoProxyCreator#shouldSkip:处理切面中通知advisors
	if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

	// 切点标识的切入类则会选择代理方式返回代理对象
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
	if (specificInterceptors != DO_NOT_PROXY) {
		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;
}
  • 普通bean添加到集合advisedBeans中后直接返回。
  • 切面类因为步骤2.1也会直接返回。
  • 切点标识的切入类则会选择代理方式返回代理对象。

3、初始化全部候选通知Advice

候选通知包含Before、After、AfterReturning、AfterThrowing、Around等。
通过步骤#2中postProcessBeforeInstantiation、postProcessAfterInitialization均涉及候选通知Advice的初始化。

通过AspectJAwareAdvisorAutoProxyCreator#shouldSkip#findCandidateAdvisors 处理切面中的通知(advisors)。

3.1、预加载候选通知Advice信息

在服务启动过程中初始化IOC容器bean之前,候选通知Advice信息就可能初始化于缓存advisorsCache中。

public List<Advisor> buildAspectJAdvisors() {
	// 切面名:@Aspect注解的类名
	List<String> aspectNames = this.aspectBeanNames;
	if (aspectNames == null) {// 提前将切面涉及的各类通知缓存处理(事务|AOP)
		synchronized (this) {
			aspectNames = this.aspectBeanNames;
			if (aspectNames == null) {
				List<Advisor> advisors = new ArrayList<>();
				aspectNames = new ArrayList<>();
				// aop功能中在这里传入的是Object.class类型,代表从容器中获取到所有组件的名称,然后一一遍历。如果容器中组件过多则遍历过程非常耗时。所以使用缓存处理切面信息,提高性能。
				//事务功能是直接从容器中获取advisor.class类型的,相对Object.class类型选择范围很小,而且不耗能,所以针对事务的切面信息没有选择缓存处理。
				String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
						this.beanFactory, Object.class, true, false);
				for (String beanName : beanNames) {//服务中所有bean name
					...
					// 判断当前类是否存在Aspect注解|是否是切面
					if (this.advisorFactory.isAspect(beanType)) {
						aspectNames.add(beanName);
						AspectMetadata amd = new AspectMetadata(beanType, beanName);
						if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
							MetadataAwareAspectInstanceFactory factory =
									new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
							// 解析切面类:ReflectiveAspectJAdvisorFactory#getAdvice
							List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
							if (this.beanFactory.isSingleton(beanName)) {
								// 将切面中通知信息加入缓存
								this.advisorsCache.put(beanName, classAdvisors);
							}
							else {
								this.aspectFactoryCache.put(beanName, factory);
							}
							advisors.addAll(classAdvisors);
						}
						else {
							...
							MetadataAwareAspectInstanceFactory factory =
									new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
							this.aspectFactoryCache.put(beanName, factory);
							advisors.addAll(this.advisorFactory.getAdvisors(factory));
						}
					}
				}
				this.aspectBeanNames = aspectNames;
				return advisors;
			}
		}
	}

	if (aspectNames.isEmpty()) {
		return Collections.emptyList();
	}
	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;
}

在这里插入图片描述

ReflectiveAspectJAdvisorFactory#getAdvice:针对切面每个通知都会生成一个实例一一对应。

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
	Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
	String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
	...
	List<Advisor> advisors = new ArrayList<>();
	for (Method method : getAdvisorMethods(aspectClass)) {//获取切面类所有方法
		Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
		if (advisor != null) {
			advisors.add(advisor);
		}
	}
	...
	return advisors;
}

InstantiationModelAwarePointcutAdvisorImpl#instantiateAdvice#getAdvice

public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
	...
	switch (aspectJAnnotation.getAnnotationType()) {
		case AtPointcut:
			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;
	}
....
	return springAdvice;
}

3.2、AspectJAwareAdvisorAutoProxyCreator后置处理器

该后置处理器是spring默认初始化的后置处理器,所以在初始化IOC容器中bean的时候都会触发postProcessAfterInitialization、postProcessBeforeInstantiation。

在步骤#2中所有bean初始化过程中只要当前类不是切面类,均会执行shouldSkip方法。

protected boolean shouldSkip(Class<?> beanClass, String beanName) {
	// TODO: Consider optimization by caching the list of the aspect names
	List<Advisor> candidateAdvisors = findCandidateAdvisors();
	for (Advisor advisor : candidateAdvisors) {
		// 如果存在候选通知Advisor是AspectJ相关的通知,则直接跳过
		if (advisor instanceof AspectJPointcutAdvisor &&
				((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
			return true;
		}
	}
	return super.shouldSkip(beanClass, beanName);
}

AspectJ与Spring中aop存在差别。

protected List<Advisor> findCandidateAdvisors() {
	// Add all the Spring advisors found according to superclass rules.
	// 以下是涉及事务方面的通知(Advisors)
	List<Advisor> advisors = super.findCandidateAdvisors();
	// Build Advisors for all AspectJ aspects in the bean factory.
	// 以下是涉及 aop 切面的通知(Advisors)
	if (this.aspectJAdvisorsBuilder != null) {
		//直接从advisorsCache缓存中获取全部的候选通知Advice
		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
	}
	return advisors;
}

通过#3.1得到,所有候选通知Advice都已经初始化于缓存advisorsCache之中。

4、切入类动态代理

DefaultAopProxyFactory#createAopProxy

public Object getProxy(@Nullable ClassLoader classLoader) {
	return createAopProxy().getProxy(classLoader);
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
			return new JdkDynamicAopProxy(config);
		}
		//ObjenesisCglibAopProxy extends CglibAopProxy implements AopProxy
		return new ObjenesisCglibAopProxy(config);
	}
	else {
		// JdkDynamicAopProxy implements AopProxy
		return new JdkDynamicAopProxy(config);
	}
}

getProxy

  • JdkDynamicAopProxy
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
	Assert.notNull(config, "AdvisedSupport must not be null");
	if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
		throw new AopConfigException("No advisors and no TargetSource specified");
	}
	this.advised = config;
}
  • ObjenesisCglibAopProxy

门面模式:

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
	
	try {
		Class<?> rootClass = this.advised.getTargetClass();
		Class<?> proxySuperClass = rootClass;
		if (ClassUtils.isCglibProxyClass(rootClass)) {
			proxySuperClass = rootClass.getSuperclass();
			Class<?>[] additionalInterfaces = rootClass.getInterfaces();
			for (Class<?> additionalInterface : additionalInterfaces) {
				this.advised.addInterface(additionalInterface);
			}
		}

		// 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 ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

		Callback[] callbacks = getCallbacks(rootClass);// cglib中涉及的callback
		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.
		// ObjenesisCglibAopProxy#createProxyClassAndInstance
		return createProxyClassAndInstance(enhancer, callbacks);
	}
	...
}

5、织入过程源码分析

Cglib

CglibAopProxy 中静态内部类 DynamicAdvisedInterceptor

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
	public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
		TargetSource targetSource = this.advised.getTargetSource();//被代理类
		...
		if (this.advised.exposeProxy) {
			// Make invocation available if necessary.
			oldProxy = AopContext.setCurrentProxy(proxy);
			setProxyContext = true;
		}
		// 将aop中自定义切面中每个通知转化为对应拦截器
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
	}
}

JDK

JdkDynamicAopProxy#invoke

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	Object oldProxy = null;
	boolean setProxyContext = false;
	TargetSource targetSource = this.advised.targetSource;//被代理类
	Object target = null;

	try {
		...
		target = targetSource.getTarget();
		Class<?> targetClass = (target != null ? target.getClass() : null);
		//获取到切面中全部通知
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
		if (chain.isEmpty()) {
			Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
			retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
		}
		else {
			// We need to create a method invocation...
			MethodInvocation invocation =
					new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
			// Proceed to the joinpoint through the interceptor chain.
			// 责任链模式调用通知
			retVal = invocation.proceed();
		}
		...
		return retVal;
	}
	...
}
public Object proceed() throws Throwable {
	//	We start with an index of -1 and increment early.
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		// 调用环绕通知
		return invokeJoinpoint();
	}

	Object interceptorOrInterceptionAdvice =
			this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
	if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
		...
	}
	else {
		// this 表示当前类 ReflectiveMethodInvocation
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
	}
}

interceptorsAndDynamicMethodMatchers:
在这里插入图片描述

  • AspectJAfterThrowingAdvice
public Object invoke(MethodInvocation mi) throws Throwable {
	try {
		return mi.proceed();
	}
	catch (Throwable ex) {
		if (shouldInvokeOnThrowing(ex)) {
			invokeAdviceMethod(getJoinPointMatch(), null, ex);
		}
		throw ex;
	}
}
  • AfterReturningAdviceInterceptor
public Object invoke(MethodInvocation mi) throws Throwable {
	Object retVal = mi.proceed();
	this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
	return retVal;
}
  • AspectJAfterAdvice
public Object invoke(MethodInvocation mi) throws Throwable {
	try {
		return mi.proceed();
	}
	finally {
		invokeAdviceMethod(getJoinPointMatch(), null, null);
	}
}
  • AspectJAroundAdvice
public Object invoke(MethodInvocation mi) throws Throwable {
	if (!(mi instanceof ProxyMethodInvocation)) {
		throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
	}
	ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
	ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
	JoinPointMatch jpm = getJoinPointMatch(pmi);
	return invokeAdviceMethod(pjp, jpm, null, null);
}
  • MethodBeforeAdviceInterceptor
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
	// 调用切面类中的before通知
	this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
	return mi.proceed();
}

在这里插入图片描述
在这里插入图片描述

isInfrastructureClass方法

protected boolean isInfrastructureClass(Class<?> beanClass) {
	return (super.isInfrastructureClass(beanClass) ||
			(this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
}
public boolean isAspect(Class<?> clazz) {
	return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}

private boolean hasAspectAnnotation(Class<?> clazz) {
	return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
}

通过判断是否存在注解@Aspect识别当前是否为切面类。

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

只要当前类是Advice、Pointcut、Advisor、AopInfrastructureBean类中其中一个都可以认定为是切面类。【是否意味着切面类也可以通过继承来实现呢?】

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值