Spring源码分析之AOP

9 篇文章 0 订阅
7 篇文章 0 订阅

AOP是什么

面向切面的程序设计(Aspect-oriented programming,AOP,又译作面向方面的程序设计剖面导向程序设计),是计算机科学中的一种程序设计思想,旨在将横切关注点与业务主体进行进一步分离,以提高程序代码的模块化程度。通过在现有代码基础上增加额外的通知(Advice)机制,能够对被声明为“切点(Pointcut)”的代码块进行统一管理与装饰。

怎么在Spring里使用AOP

Spring里,AOP通过EnableAspectJAutoProxy注解开启。默认情况下,Spring会通过AopAutoConfiguration自动引入这个注解

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(Advice.class)
	static class AspectJAutoProxyingConfiguration {

		@Configuration(proxyBeanMethods = false)
		@EnableAspectJAutoProxy(proxyTargetClass = false)
		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false")
		static class JdkDynamicAutoProxyConfiguration {

		}

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

		}

	}
}

可以看到,如果我们不主动设置spring.aop.auto=false。那么Spring默认会启用AOP。接下来,我们可以通过在类上标注Aspect即可使用AOP

package org.example.aspect;

@Aspect
@Component
public class SampleAspect {

    @Pointcut("execution(* org.example.xxx.*.*(..))")
    private void executionPointcut() {

    }

    @After(value = "executionPointcut()")
    public void doAfter() {
        
    }
}

源码分析

1. AOP初始化

1.1 初始化AspectJAutoProxyRegistrar

EnableAspectJAutoProxy通过Import注解引入了AspectJAutoProxyRegistrar

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

AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrarSpring在初始化AopAutoConfiguration时把所有通过Import注解引入的ImportBeanDefinitionRegistrar实现类拿出来进行初始化,并调用其registerBeanDefinitions函数

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

}

1.2 初始化AnnotationAwareAspectJAutoProxyCreator

AspectJAutoProxyRegistrar 则在registerBeanDefinitions注册了一个AnnotationAwareAspectJAutoProxyCreatorBeanDefinition

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

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

AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessorSpring会在初始化普通Bean之前初始化所有BeanPostProcessor

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {

		public void refresh() throws BeansException, IllegalStateException {
					// 初始化BeanProcessor来拦截Bean的创建
					registerBeanPostProcessors(beanFactory);
	
					// 初始化所有剩下的非懒加载的Bean,比如我们写的Service
					finishBeanFactoryInitialization(beanFactory);
		}
}

1.3 初始化切面方法跟切点

另外,AnnotationAwareAspectJAutoProxyCreator实现了InstantiationAwareBeanPostProcessorSpring 会在Bean创建时调用其postProcessBeforeInstantiation方法对Bean进行处理。

在第一次调用该方法时,AnnotationAwareAspectJAutoProxyCreator会初始化切面

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
	
	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
		Object cacheKey = getCacheKey(beanClass, beanName);

		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
			//判断当前BeanName对应的Bean是否应该被代理
			//并将判断结果保存下来,避免后续的后处理方法重复计算
			//在第一次判断时,会在shouldSkip里扫描所有Bean进行切面初始化
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		//如果为AbstractAutoProxyCreator注入了自定义的TargetSourceCreator
		//则通过TargetSourceCreator创建的Bean都被被AOP代理
		//TargetSourceCreator默认为空
		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;
	}
}

切面初始化

public class BeanFactoryAspectJAdvisorsBuilder {

		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<>();
							
							//拿到容器里所有的beanName
							String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
									this.beanFactory, Object.class, true, false);
							for (String beanName : beanNames) {

								Class<?> beanType = this.beanFactory.getType(beanName, false);
								
								//判断类上是否标注Aspect,以及判断该class是否已经被代码式的Aspectj处理过
								if (this.advisorFactory.isAspect(beanType)) {
									aspectNames.add(beanName);
									AspectMetadata amd = new AspectMetadata(beanType, beanName);
									MetadataAwareAspectInstanceFactory factory =
												new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);

										//从类中拿到所有带有Before、Around等注解的方法,
										//将这些方法包装成MethodInterceptor放入Advisor,MethodInterceptor#invoke为增强方法的调用入口
										//将Advisor排好顺序组成List返回
										List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);

										this.advisorsCache.put(beanName, classAdvisors);
										advisors.addAll(classAdvisors);
								}
							}
							this.aspectBeanNames = aspectNames;
							return advisors;
						}
					}
				}
			}
}

Advisor排序

public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
		private static final Comparator<Method> adviceMethodComparator;
	
		static {
			
			Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
					//按照注解顺序设置方法对应的advisor的顺序
					//在AspectJAfterAdvice里,会先将请求继续向拦截器链后传播,
					//对增强方法的调用是在后面的finnaly块里。所以这里的After顺序即使在AfterReturning前面也没关系
					//另外,因为在finnly块里触发,所以即使后续的调用抛出了未捕获的异常,After指定的增强方法也会被执行
					new InstanceComparator<>(
							Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
	
					(Converter<Method, Annotation>) method -> {
							//如果方法上没有标注上面的几个注解,则返回null,null会排在最后
						AspectJAnnotation<?> ann = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
						return (ann != null ? ann.getAnnotation() : null);
					});
			Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
			adviceMethodComparator = adviceKindComparator.thenComparing(methodNameComparator);
		}
}

判断method是否属于切面方法

	
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
		public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
				int declarationOrderInAspect, String aspectName) {
	
				//获取切点信息,如果candidateAdviceMethod不是切面方法,则返回null
				AspectJExpressionPointcut expressionPointcut = getPointcut(
						candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
				if (expressionPointcut == null) {
					return null;
				}
		
				return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
						this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
		}	

		private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
				//在方法上查找Aspectj的相关注解(Around、After等)
				AspectJAnnotation<?> aspectJAnnotation =
						AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
				if (aspectJAnnotation == null) {
					return null;
				}
		
				...
		}
}

2. 生成代理对象

AbstractAutoProxyCreator实现了BeanPostProcessor,在创建Bean时,Spring会调用AbstractAutoProxyCreator#postProcessAfterInitializationBean进行处理

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
	
		@Override
		public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
			if (bean != null) {
				Object cacheKey = getCacheKey(bean.getClass(), beanName);
				if (this.earlyProxyReferences.remove(cacheKey) != bean) {
					//对bean进行包装,返回代理bean
					return wrapIfNecessary(bean, beanName, cacheKey);
				}
			}
			return bean;
		}

		protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
				//如果bean有TargetSourceCreator创建,说明已经被代理过了,直接返回
				if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
					return bean;
				}
				//拿出缓存的检测的结果进行判断
				if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
					return bean;
				}
				//初步判断bean是否可以被代理
				if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
					this.advisedBeans.put(cacheKey, Boolean.FALSE);
					return bean;
				}
		
				//根据切点Point的表达式获得符合当前bean的所有advisor
				//如果当前bean不在切点的指向中,则返回DO_NOT_PROXY
				Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
				if (specificInterceptors != DO_NOT_PROXY) {
					this.advisedBeans.put(cacheKey, Boolean.TRUE);
					//创建代理对象,将所有advisor包装成DynamicAdvisedInterceptor,
					//其intercept方法为所有增强方法的统一入口,这个类来自Spring
					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;
	}
}

选择代理对象的创建方式

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {	
		@Override
		public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
			if (!NativeDetector.inNativeImage() &&
					(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
				Class<?> targetClass = config.getTargetClass();
				
				//如果targetClass是接口类型或者是通过Proxy.getProxyClass生成的或者类名里包含$$Lambda
				//则使用JDK动态代理
				if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
					return new JdkDynamicAopProxy(config);
				}
				//使用cglib,ASM修改字节码的方式生产代理类
				return new ObjenesisCglibAopProxy(config);
			}
			else {
				return new JdkDynamicAopProxy(config);
			}
		}
}

3. 访问代理对象

DispatcherServlet 找到对应的实例跟方法后通过反射进行调用(前面Spring Mvc博文里已分析过),此时会遍历代理对象上的所有MethodInterceptor,

public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {

		public Object proceed() throws Throwable {
			//如果拦截器遍历完了,则调用目标方法
			if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
				return invokeJoinpoint();
			}
	
			//遍历所有增强器MethodInterceptor,
			//遍历方式是在MethodInterceptor里调用MethodInvocation#proceed
			//每次进入该方法,都会使currentInterceptorIndex增加1,从而达成遍历
			Object interceptorOrInterceptionAdvice =
					this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
			
			//调用MethodInterceptor#invoke
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
}

增强方法实际执行的顺序图

在这里插入图片描述

接下来看看每个增强注解对应的MethodInterceptor处理类是怎么进行请求处理与传递的

1. AspectJAroundAdvice

public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {

	@Override
	@Nullable
	public Object invoke(MethodInvocation mi) throws Throwable {
		...
		ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
		ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
		JoinPointMatch jpm = getJoinPointMatch(pmi);
		//调用Around对应的增强方法,并将mi传如增强方法
		//mi持有了所有的拦截/增强器信息,通过Joinpoint#proceed实现请求的传递
		//所以,around增强方法里需要注意接收Joinpont的实例并调用其proceed方法
		return invokeAdviceMethod(pjp, jpm, null, null);
	}

}

2. MethodBeforeAdviceInterceptor

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {

	private final MethodBeforeAdvice advice;

	public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
		Assert.notNull(advice, "Advice must not be null");
		this.advice = advice;
	}

	@Override
	@Nullable
	public Object invoke(MethodInvocation mi) throws Throwable {
		//调用before增强方法
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
		//向后传递
		return mi.proceed();
	}

}

3. AspectJAfterAdvice

public class AspectJAfterAdvice extends AbstractAspectJAdvice
		implements MethodInterceptor, AfterAdvice, Serializable {

		public AspectJAfterAdvice(
				Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
	
			super(aspectJBeforeAdviceMethod, pointcut, aif);
		}
	
	
		@Override
		@Nullable
		public Object invoke(MethodInvocation mi) throws Throwable {
			try {
				//先向后传递
				return mi.proceed();
			}
			finally {
				//执行After方法
				invokeAdviceMethod(getJoinPointMatch(), null, null);
			}
		}

}

4. AfterReturningAdviceInterceptor

public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {

	private final AfterReturningAdvice advice;

	public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
		Assert.notNull(advice, "Advice must not be null");
		this.advice = advice;
	}

	@Override
	@Nullable
	public Object invoke(MethodInvocation mi) throws Throwable {

		//向后传递
		Object retVal = mi.proceed();
		//调用AfterReturning方法
		this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
		return retVal;
	}

}

5. AspectJAfterThrowingAdvice

public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
		implements MethodInterceptor, AfterAdvice, Serializable {

		public AspectJAfterThrowingAdvice(
				Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
	
			super(aspectJBeforeAdviceMethod, pointcut, aif);
		}
	
		@Override
		@Nullable
		public Object invoke(MethodInvocation mi) throws Throwable {
			try {
				//向后传递
				return mi.proceed();
			}
			catch (Throwable ex) {
				//判断增强器上定义的异常类型是否匹配
				if (shouldInvokeOnThrowing(ex)) {
					//调用AfterThrowing方法
					invokeAdviceMethod(getJoinPointMatch(), null, ex);
				}
				throw ex;
			}
		}
	
		/**
		 * In AspectJ semantics, after throwing advice that specifies a throwing clause
		 * is only invoked if the thrown exception is a subtype of the given throwing type.
		 */
		private boolean shouldInvokeOnThrowing(Throwable ex) {
			return getDiscoveredThrowingType().isAssignableFrom(ex.getClass());
		}

}

6. ExposeInvocationInterceptor

public final class ExposeInvocationInterceptor implements MethodInterceptor, PriorityOrdered, Serializable {
	
		private static final ThreadLocal<MethodInvocation> invocation =
					new NamedThreadLocal<>("Current AOP method invocation");

		@Override
		@Nullable
		public Object invoke(MethodInvocation mi) throws Throwable {
			MethodInvocation oldInvocation = invocation.get();
			//将MethodInvocation绑定到当前线程的本地变量里,
			//从而实现在其他地方访问MethodInvocation
			//但不建议这样做,因为AOP对于被代理对象来说应该是无感知的,不应该产生这种依赖
			invocation.set(mi);
			try {
				return mi.proceed();
			}
			finally {
				invocation.set(oldInvocation);
			}
		}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值