SpringAOP源码解析(二)
在上篇文章中我们简单介绍了aop导入过程,其中
@EnableAspectJAutoProxy
注解最主要的功能就是想Spring注册了
AnnotationAwareAspectJAutoProxyCreator
,下面我们先看一眼此类的继承图:
观察类图可知,AnnotationAwareAspectJAutoProxyCreator
这个类间接实现了BeanPostProcessor
接口。我们知道在Spring实例化Bean的前后会分别调用实现BeanPostProcessor
接口类的postProcessBeforeInstantiation
和postProcessAfterInitialization
方法。AOP也是基于这两个方法实现的。
postProcessBeforeInstantiation
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
...
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
...
}
shouldSkip
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
...
List<Advisor> candidateAdvisors = findCandidateAdvisors();
...
}
findCandidateAdvisors
我们知道一般在使用aop功能时会使用@Aspect注解,被此注解标注的类中会有@Pointcut
、@Before
、@After
、@AfterReturning
、@AfterThrowing
、@Around
标注的方法,后五个被称为Advice。Pointcut
+Advice
被我们称为Advisor
。此方法就是寻找所有的Advisor
。
findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
//找到所有的Advisor
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
//主要看这里,创建候选的切面 对@Aspect注解的类进行处理
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
buildAspectJAdvisors
找到配对的Pointcut
与Advice
构建Advisor
buildAspectJAdvisors
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<>();
//获取spring容器中的所有bean的名称BeanName
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
// We must be careful not to instantiate beans eagerly as in this case they
// would be cached by the Spring container but would not have been weaved.
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
//判断类上是否有@Aspect注解
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
//创建获取有@Aspect注解类的实例工厂,负责获取有@Aspect注解类的实例
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
//创建切面advisor对象
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 {
// 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);
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;
}
getAdvisors
getAdvisors
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
...
List<Advisor> advisors = new ArrayList<>();
//这里循环没有@Pointcut注解的方法
for (Method method : getAdvisorMethods(aspectClass)) {
//获取Advisor
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
...
}
getAdvisorMethods(aspectClass)
获得类中所有没有@Pointcut注解的方法。getAdvisor
生成增强实例
getAdvisor
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
//获取pointCut对象,最重要的是从注解中获取表达式
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
//创建Advisor切面类,这才是真正的切面类,一个切面类里面肯定要有1、pointCut 2、advice
//这里pointCut是expressionPointcut, advice 增强方法是 candidateAdviceMethod
//根据方法、切点、AOP实例工厂、类名、序号生成切面实例
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
getPointcut
new InstantiationModelAwarePointcutAdvisorImpl()
getPointcut
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
//从候选的增强方法里面 candidateAdviceMethod 找有有注解
//Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class
//并把注解信息封装成AspectJAnnotation对象
//查询方法上的切面注解,根据注解生成相应类型的AspectJAnnotation,在调用AspectJAnnotation的构造函数的同时
//根据注解value或pointcut属性得到切点表达式,有argNames则设置参数名称
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
//创建一个PointCut类,并且把前面从注解里面解析的表达式设置进去
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
return ajexp;
}
findAspectJAnnotationOnMethod
new AspectJExpressionPointcut()
findAspectJAnnotationOnMethod
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
//Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class
for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
//找到Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class
//注解的方法,并且把注解里面的信息封装成AspectJAnnotation对象
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
findAnnotation
findAnnotation
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
A result = AnnotationUtils.findAnnotation(method, toLookFor);
if (result != null) {
//把注解里面的信息解析出来,然后包装成AspectJAnnotation对象
//获取注解上的参数(argNames)
return new AspectJAnnotation<>(result);
}
else {
return null;
}
}
至此在getAdvisor
方法中调用的getPointcut
方法逻辑分析完毕,下面分析getAdvisor
方法中调用new InstantiationModelAwarePointcutAdvisorImpl()
的逻辑。
new InstantiationModelAwarePointcutAdvisorImpl()
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
...
//创建advice对象
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
...
}
instantiateAdvice
instantiateAdvice
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
//创建Advice对象
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
getAdvice
getAdvice
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
//获取有@Aspect注解的类
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
//找到candidateAdviceMethod方法上面的注解,并且包装成AspectJAnnotation对象,这个对象中就有注解类型
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
...
//根据不同的注解类型创建不同的advice类实例
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
case AtAround:
//实现了MethodInterceptor接口
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtBefore:
//实现了MethodBeforeAdvice接口,没有实现MethodInterceptor接口
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
//实现了MethodInterceptor接口
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
//实现了AfterReturningAdvice接口,没有实现MethodInterceptor接口
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
//实现了MethodInterceptor接口
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);
}
// Now to configure the advice...
//设置通知方法所属的类
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
//获取注解中的argNames属性参数名称
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
//计算argNames和类型的对应关系
springAdvice.calculateArgumentBindings();
return springAdvice;
}
小结
至此,在AnnotationAwareAspectJAutoProxyCreator
中postProcessBeforeInstantiation
方法分析完毕,即在bean实列化前aop准备工作分析完毕。下面分析bean实列化后aop所做的工作,即分析AnnotationAwareAspectJAutoProxyCreator
中postProcessAfterInitialization
方法。
postProcessAfterInitialization
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator
中的postProcessAfterInitialization
方法调用栈如下:
此方法核心代码如下:
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
...
return wrapIfNecessary(bean, beanName, cacheKey);
...
}
wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
...
//判断当前bean是否有切面
//创建当前bean的代理,如果这个bean有advice的话,重点看,重要程度5
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
...
//如果有切面,则生成该bean的代理
//把被代理对象bean实例封装到SingletonTargetSource对象中
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
...
}
-
getAdvicesAndAdvisorsForBean
找到所有的合格的切面 -
createProxy
如果有合格的切面,则创建代理
getAdvicesAndAdvisorsForBean
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
...
//找到合格的切面,重点看
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
...
}
findEligibleAdvisors
findEligibleAdvisors
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//找到候选的切面,其实就是一个寻找有@Aspectj注解的过程,把工程中所有有这个注解的类封装成Advisor返回
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//判断候选的切面是否作用在当前beanClass上面,就是一个匹配过程。。现在就是一个匹配
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
//针对@Aspect注解切面添加了一个默认的切面 DefaultPointcutAdvisor
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
//对有@Order@Priority进行排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
-
findCandidateAdvisors
找到所有的Advisor
。我们知道一般在使用aop功能时会使用@Aspect注解,被此注解标注的类中会有@Pointcut
、@Before
、@After
、@AfterReturning
、@AfterThrowing
、@Around
标注的方法,后五个被称为Advice。Pointcut
+Advice
被我们称为Advisor
。此方法就是寻找所有的Advisor
。 -
findAdvisorsThatCanApply
-
extendAdvisors
针对@Aspect注解切面添加了一个默认的切面 DefaultPointcutAdvisor
findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
//找到所有的Advisor
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
//主要看这里,创建候选的切面 对@Aspect注解的类进行处理
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
buildAspectJAdvisors
buildAspectJAdvisors
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
...
}
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;
}
- 由于在
postProcessBeforeInstantiation
中已经找到了所有的Advisor,顾此处的advisors必定是从缓存里拿的。同理,此处aspectNames不为空,所以第一个if不会执行。
findAdvisorsThatCanApply
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
//将beanName放入ThreadLocal中
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
//看看当前类是否在这些切面的pointCut中..掉类和方法的match过程
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
//将ThreadLocal置空
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
findAdvisorsThatCanApply
findAdvisorsThatCanApply
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
...
//调用pointCut中的ClassFilter 和methodMatcher的match方法的过程
for (Advisor candidate : candidateAdvisors) {
...
//candidate切面
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
...
}
canApply
canApply
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
...
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
...
}
canApply
canApply
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
//调用ClassFilter的matches方法,判断类是否匹配
//这里会将形如@Around("pc1()")配置中的pc1找到pc1方法从而找到真正的pointCut表达式
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
//验证注解的作用域是否可以作用于方法上
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
...
//判断类中方法是否匹配,,有些可能是方法上面有注解的拦截,所以需要判断方法是否匹配
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
//获取类所实现的所有接口和所有类层级的方法,循环验证
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
-
若
targetClass
中有方法匹配切面则返回true。 -
至此,我们完成了对拦截目标bean的Advisor的收集,即完成了对
wrapIfNecessary
中getAdvicesAndAdvisorsForBean
方法的分析,下面我们将进行对wrapIfNecessary
中createProxy
方法的分析
extendAdvisors
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}
makeAdvisorChainAspectJCapableIfNecessary
makeAdvisorChainAspectJCapableIfNecessary
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
...
advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
...
}
- 在所有advisor前添加一个全局advisor
createProxy
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();
//把AnnotationAwareAspectJAutoProxyCreator中的某些属性copy到proxyFactory中
proxyFactory.copyFrom(this);
//判断是否使用Cglib动态代理
if (!proxyFactory.isProxyTargetClass()) {
//如果配置开启使用则直接设置开启
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
//如果没有配置开启则判断bean是否有合适的接口使用JDK的动态代理(JDK动态代理必须是带有接口的类,如果类没有实现任何接口则只能使用Cglib动态代理)
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//组装advisor
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
//把advisor加入到proxyFactory
//添加所有增强
proxyFactory.addAdvisors(advisors);
//把targetSource对象加入到proxyFactory
//设置要代理的类
proxyFactory.setTargetSource(targetSource);
//Spring的一个扩展点,默认实现为空。留给我们在需要对代理进行特殊操作的时候实现
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//获取代理对象
//使用代理工厂获取代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}
getProxy
getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
createAopProxy
createAopProxy
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
createAopProxy
createAopProxy
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (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)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
- 根据条件选择Jdk代理或者Cglib代理
小结
自此对目标bean的代理创建完毕。