27.AOP源码:寻找合适的Advisor

121 阅读24分钟

为什么AOP能生效?是因为我们在配置类上面使用了注解@EnableAspectJAutoProxy,@EnableAspectJAutoProxy导入AspectJAutoProxyRegistrar的同时还注入了AnnotationAwareAspectJAutoProxyCreator。所以我们看AOP的源码要从@EnableAspectJAutoProxy开始。

对象是如何被代理的?或者说代理的过程是怎么样的?

在AnnotationAwareAspectJAutoProxyCreator的后置处理方法中调用AbstractAutoProxyCreator#wrapIfNecessary方法。代理的过程要从这个方法开始看。

本文就是围绕上面2个问题展开的。

鉴于篇幅,AbstractAutoProxyCreator#wrapIfNecessary方法只讲一部分。

SpringAop示例代码

package aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.PriorityOrdered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class Aop implements PriorityOrdered {

    //指定切入点表达式,拦截那些方法,即为那些类生成代理对象
    //@Pointcut("execution(* com.aop.UserDao.save(..))")  ..代表所有参数
    //@Pointcut("execution(* com.aop.UserDao.*())")  指定所有的方法
    //@Pointcut("execution(* com.aop.UserDao.save())") 指定save方法

    @Pointcut("execution(* aop.*.*(..))")
    public void pointCut(){

    }

    @Before("pointCut()")
    public void Before(){
        System.out.println("Before");
    }

    @After("pointCut()")
    public void After(){
        System.out.println("After");
    }

    @AfterThrowing("pointCut()")
    public void AfterThrowing(){
        System.out.println("AfterThrowing");
    }

    @AfterReturning("pointCut()")
    public void AfterReturning(){
        System.out.println("AfterReturning");
    }

    @Around("pointCut()")
    public void Around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("Around Before");
        joinPoint.proceed();
        System.out.println("Around After");
    }

    @Override
    public int getOrder() {
        return 1;
    }
}

package aop;

import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

@Component
public class AopLog implements LogService{

	public String log() {
		System.out.println("----log----");
		return "1";
	}

	@Override
	public void print() {
		System.out.println("----print----");
	}
}
package aop;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

//@EnableAspectJAutoProxy(proxyTargetClass = true)
@EnableAspectJAutoProxy(proxyTargetClass = false)
@ComponentScan()
public class BeanConfig {

}
    package aop;

    import org.springframework.stereotype.Component;

    @Component
    public interface LogService {

    	  void print();
    }


package aop;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestAopCondition {
    public static void main(String[] args) {

        System.out.println(Aop.class.isInterface());

        /**
         * 创建一个BeanDefinition读取器 根据注解读取
         * 创建一个BeanDefinition扫描器 能够扫描一个类或者包 转换成bd
         **/
        AnnotationConfigApplicationContext context = new 
                                        AnnotationConfigApplicationContext();
        //注册配置类
        context.register(BeanConfig.class);
        context.refresh();
        //如果使用的是JDK代理 即AopLog有接口 那么使用下面的
        LogService aopLog = context.getBean("aopLog", LogService.class);
        aopLog.print();
        //如果使用的是JDK代理 即AopLog没有接口 那么使用下面的
        /*AopLog aopLog = context.getBean("aopLog", AopLog.class);
        aopLog.log();
        aopLog.print();*/
    }
}

@EnableAspectJAutoProxy

会导入AspectJAutoProxyRegistrar

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(AspectJAutoProxyRegistrar.class)
    public @interface EnableAspectJAutoProxy {
        //proxyTargetClass:作用是确定代理方式 确定是cglib还是jdk
        boolean proxyTargetClass() default false;
        //exposeProxy:true 通过ThreadLocal保存当前代理实例
        boolean exposeProxy() default false;
    ​
    }

其中有2个属性。

proxyTargetClass:作用是确定代理方式 确定是cglib还是jdk

exposeProxy:true 通过ThreadLocal保存当前代理实例

1.导入AspectJAutoProxyRegistrar

AspectJAutoProxyRegistrar在哪里被加载的?

AspectJAutoProxyRegistrar被加载的方法:

ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsFromRegistrars

private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
    registrars.forEach((registrar, metadata) ->
            //metadata是BeanConfig上的注解
            //@EnableAspectJAutoProxy(proxyTargetClass = false)
            //@ComponentScan()
            //调用AspectJAutoProxyRegistrar的registerBeanDefinitions        
            registrar.registerBeanDefinitions(metadata, this.registry));
}

2.注入AnnotationAwareAspectJAutoProxyCreator

在AspectJAutoProxyRegistrar的registerBeanDefinitions方法中

AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessor。

注册AnnotationAwareAspectJAutoProxyCreator对应的BeanDefinition意味着

在PopulateBean的时候可以被拦截调用。

    class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
     //@EnableAspectJAutoProxy(proxyTargetClass = false)
     //@ComponentScan()
     //importingClassMetadata是BeanConfig上的注解
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, 
    BeanDefinitionRegistry registry) {
         //注入AnnotationAwareAspectJAutoProxyCreator对应的bd
        //AnnotationAwareAspectJAutoProxyCreator间接继承了AbstractAutoProxyCreator
        //通过AbstractAutoProxyCreator可以创建代理类

        //registerAspectJAnnotationAutoProxyCreatorIfNecessary 为什么要这么叫呢
        //感觉是如果事务和aop同时存在主要其中一个注册就可以了
        //注意:切面注册的是AnnotationAwareAspectJAutoProxyCreator
        //事务会注入InfrastructureAdvisorAutoProxyCreator
        //如果事务和切面同时存在使用AnnotationAwareAspectJAutoProxyCreator
        //return registerOrEscalateApcAsRequired
        //(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

        //读取BeanConfig上的注解@EnableAspectJAutoProxy属性
        AnnotationAttributes enableAspectJAutoProxy 
        = AnnotationConfigUtils.attributesFor
                                                        (importingClassMetadata, 
                                                        EnableAspectJAutoProxy.class);

        if (enableAspectJAutoProxy != null) {
        //设置属性proxyTargetClass 这个属性的作用是确定代理方式 确定是cglib还是jdk
                if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                        AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
                }

        //exposeProxy的属性的值是true的话
        //就通过ThreadLocal保存当前代理实例,可通过以下方法获取到代理
        //((UserService)AopContext.currentProxy())
            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                    AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }
}

调用链路图

image.png

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareMethods(beanName, bean);
                return null;
        }, getAccessControlContext());
    }else {
        //设置Spring的上下文组件
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        /***
         * BeanPostProcessor 的 before方法
         *  1.获取该bean所有的BeanPostProcessor
         *  2.依次调用BeanPostProcessor的postProcessBeforeInitialization
         */
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        /***
         * 触发init方法
         */
        invokeInitMethods(beanName, wrappedBean, mbd);
    }catch (Throwable ex) {
        throw new BeanCreationException(
                        (mbd != null ? mbd.getResourceDescription() : null),
                        beanName, "Invocation of init method failed", ex);
    }
    if (mbd == null || !mbd.isSynthetic()) {
        /***
         * BeanPostProcessor 的 after方法
         *  1.获取该bean所有的BeanPostProcessor
         *  2.依次调用BeanPostProcessor的postProcessAfterInitialization
         *  在这里被代理
         * AbstractAutoProxyCreator#postProcessAfterInitialization(Object,String)
         */
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

代理的方法入口:可以看到是在初始化bean(InitializeBean)的时候调用BeanPostProcessor的后置处理方法时,生成的代理对象。

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
 throws BeansException {
    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        //在调用完AnnotationAwareAspectJAutoProxyCreator后 会生成代理对象
        /***
        AOP切面和事务 的BeanPostProcessors如下
        0 = {ApplicationContextAwareProcessor@1068}
        1 = {ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor@1323}
        2 = {PostProcessorRegistrationDelegate$BeanPostProcessorChecker@1338}
        3 = {AnnotationAwareAspectJAutoProxyCreator@1372}
        4 = {CommonAnnotationBeanPostProcessor@1346}
        5 = {AutowiredAnnotationBeanPostProcessor@1337}
        6 = {ApplicationListenerDetector@1734}
        */
        Object current =processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}

具体一点就是:AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization方法。AnnotationAwareAspectJAutoProxyCreator继承自AbstractAutoProxyCreator,这个方法就是父类AbstractAutoProxyCreator

因此我们就从这里开始看起。

1.AbstractAutoProxyCreator#postProcessAfterInitialization

proxyTargetClass=false; optimize=false; opaque=false; exposeProxy=false; frozen=false

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
        //主要就是调用wrapIfNecessary
                    return wrapIfNecessary(bean, beanName, cacheKey);
            }
    }
    return bean;
}

2.AbstractAutoProxyCreator#wrapIfNecessary

1.findAdvisorBeans即寻找所有类型为Advisor.class或者是Advisor.class的父类的name放入advisorNames

2.遍历advisorNames获取Advisor对应的bean

3.找到了一个Advisor类型是BeanFactoryTransactionAttributeSourceAdvisor放入advisors这个是事务的advisor。

4.使用aspectJAdvisorsBuilder找到所有的Aspect。并解析Aspect下的所有的Advisor放入advisors

5.筛选所有的可应用的Advisors 就是解析切面表达式 判断是否匹配 
具体:解析表达式生成匹配器 然后和所有的方法进行匹配只要满足就可以加入eligibleAdvisors

6.在指定下标位置插入一个元素 当前下标元素以后当前下标元素后面的元素往后移动

7.排序

AOP&事务排序前
advisors = {ArrayList@1823}  size = 6 

0=org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor:advice     org.springframework.transaction.interceptor.TransactionInterceptor@2dc54ad4

1 = {InstantiationModelAwarePointcutAdvisorImpl@1832} "InstantiationModelAwarePointcutAdvisor: expression [pointCut()]; advice method [public void aop.Aop.Around(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable]; perClauseKind=SINGLETON"

2 = {InstantiationModelAwarePointcutAdvisorImpl@1833} "InstantiationModelAwarePointcutAdvisor: expression [pointCut()]; advice method [public void aop.Aop.Before()]; perClauseKind=SINGLETON"

3 = {InstantiationModelAwarePointcutAdvisorImpl@1831} "InstantiationModelAwarePointcutAdvisor: expression [pointCut()]; advice method [public void aop.Aop.After()]; perClauseKind=SINGLETON"

4 = {InstantiationModelAwarePointcutAdvisorImpl@1830} "InstantiationModelAwarePointcutAdvisor: expression [pointCut()]; advice method [public void aop.Aop.AfterReturning()]; perClauseKind=SINGLETON"

5 = {InstantiationModelAwarePointcutAdvisorImpl@1829} "InstantiationModelAwarePointcutAdvisor: expression [pointCut()]; advice method [public void aop.Aop.AfterThrowing()]; perClauseKind=SINGLETON"

AOP&事务 增加ADVISOR 排序后

eligibleAdvisors = {ArrayList@1823}  size = 7
     0 = {ExposeInvocationInterceptor$1@1828} "org.springframework.aop.interceptor.ExposeInvocationInterceptor.ADVISOR"
     1 = {InstantiationModelAwarePointcutAdvisorImpl@1829} "InstantiationModelAwarePointcutAdvisor: expression [pointCut()]; advice method [public void aop.Aop.AfterThrowing()]; perClauseKind=SINGLETON"
     2 = {InstantiationModelAwarePointcutAdvisorImpl@1830} "InstantiationModelAwarePointcutAdvisor: expression [pointCut()]; advice method [public void aop.Aop.AfterReturning()]; perClauseKind=SINGLETON"
     3 = {InstantiationModelAwarePointcutAdvisorImpl@1831} "InstantiationModelAwarePointcutAdvisor: expression [pointCut()]; advice method [public void aop.Aop.After()]; perClauseKind=SINGLETON"
     4 = {InstantiationModelAwarePointcutAdvisorImpl@1832} "InstantiationModelAwarePointcutAdvisor: expression [pointCut()]; advice method [public void aop.Aop.Around(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable]; perClauseKind=SINGLETON"
     5 = {InstantiationModelAwarePointcutAdvisorImpl@1833} "InstantiationModelAwarePointcutAdvisor: expression [pointCut()]; advice method [public void aop.Aop.Before()]; perClauseKind=SINGLETON"
    6=org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor: advice org.springframework.transaction.interceptor.TransactionInterceptor@2dc54ad4
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
                return bean;
        }
        //查看advisedBeans集合是否包含这个类的名字,如果包含就直接返回
        //advisedBeans 就是一个集合
        //用来保存不需要代理的类。比如我们上面定义的切面本身是不需要被代理的。
        //还有就是代理过也不需要代理
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
                return bean;
        }

        //isInfrastructureClass(beanClass)
        //判断我们这个业务类是否需要被代理,进入isInfrastructureClass代码
        //判断Advice、Pointcut、Advisor是否是beanClass的超类或者超接口

        //shouldSkip(beanClass, beanName)
        //主要是判断beanName不为空且不是以ORIGINAL结尾
        //2个条件都是false 说明需要代理
        if (isInfrastructureClass(bean.getClass()) 
                || shouldSkip(bean.getClass(), beanName)) {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return bean;
        }

        /***
          获取所有该bean可应用的事务和切面的Advisors
         */
        Object[] specificInterceptors = 
                getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

        //DO_NOT_PROXY = 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;
}
2.1 isInfrastructureClass:是否需要被代理?

Advice、Pointcut、Advisor等是跟切面相关的,不需要代理

protected boolean isInfrastructureClass(Class<?> beanClass) {
    //Advice.class.isAssignableFrom(beanClass)
    //判定此 Advice.class 对象所表示的类或接口与指定的 beanClass参数所表示的类或接口是否相同,
    //或是否是其超类或超接口。
    //Advice、Pointcut、Advisor等是跟切面相关的,不需要代理。 所以这里不会进入判断
    boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
                    Pointcut.class.isAssignableFrom(beanClass) ||
                    Advisor.class.isAssignableFrom(beanClass) ||
                    AopInfrastructureBean.class.isAssignableFrom(beanClass);
    if (retVal && logger.isTraceEnabled()) {
        logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
    }
    return retVal;
}
2.2isOriginalInstance
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
}

String ORIGINAL_INSTANCE_SUFFIX = ".ORIGINAL";
static boolean isOriginalInstance(String beanName, Class<?> beanClass) {
    //先判断beanClass + ".ORIGINAL" 的长度是否和beanName的长度相等
    if (!StringUtils.hasLength(beanName) || beanName.length() !=
                    beanClass.getName().length() + 
                    AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX.length()) {
            return false;
    }
    //真正判断名称是否相等
    return (beanName.startsWith(beanClass.getName()) 
        && beanName.endsWith(AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX));
}
2.3getAdvicesAndAdvisorsForBean
@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();
}

2.3.1findEligibleAdvisors

1.根据类型Advisor查找Advisor类型的bean

2.查找Aspect类型的bean根据Aspect类型解析出来advisors

3.从1 2 返回的集合中筛选可用的Advisor

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
        //查找候选advisor有2种方式
        //方式1:
        //先查找所有的类型为Advised的候选Advisors 具体就是根据类型找下面这个代码找
        //advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
        //          this.beanFactory, Advisor.class, true, false);
        
        //方式2:获取所有的ASPECT的bean,解析ASPECT类型的bean为Advisors
        //advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    
        //从所有带有@Aspect注解的bean中解析获取Advisor
        //具体一点:判断方法是否有@Pointcut注解:
        //排除带有@Pointcut注解的方法。
        //依次在剩下的方法上查找AspectJ的六种注解
        //分别是@Pointcut、@Around、@Before、@After、@AfterReturning、@AfterThrowing
        //因为上面已经排除带有@Pointcut的方法 所以只会剩下
        //@Around、@Before、@After、@AfterReturning、@AfterThrowing
        //将增强方法构建为Advisor
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        
        //筛选所有的可应用的Advisors,找到与当前bean相匹配的增强。
        //就是解析表达式 判断是否匹配 具体:解析表达式生成匹配器 
        //具体:
        //先用切面表达式做类匹配
        //获取pointcut,从方法中取出方法匹配器
        //然后和所有的方法进行匹配只要满足就可以加入eligibleAdvisors
        //Advisors 和 methods双重循环遍历
        List<Advisor> eligibleAdvisors = 
                    findAdvisorsThatCanApply
                        (candidateAdvisors, beanClass, beanName);
        //在指定下标位置插入一个元素 当前下标元素以后当前下标元素后面的元素往后移动
        //advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
        extendAdvisors(eligibleAdvisors);
        //最后排序
        if (!eligibleAdvisors.isEmpty()) {
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

2.3.1.1findCandidateAdvisors

@Override
    protected List<Advisor> findCandidateAdvisors() {
        //查找类型为Advisor
        List<Advisor> advisors = super.findCandidateAdvisors();
        //解析Aspect切面获取Advisor
        if (this.aspectJAdvisorsBuilder != null) {
            advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        }
        return advisors;
    }
public List<Advisor> buildAspectJAdvisors() {
        //里面只有一个aop
        List<String> aspectNames = this.aspectBeanNames;
​
        if (aspectNames == null) {
            synchronized (this) {
                aspectNames = this.aspectBeanNames;
                if (aspectNames == null) {
                    List<Advisor> advisors = new ArrayList<>();
                    aspectNames = new ArrayList<>();
                    //获取所有的bean
                    String[] beanNames = BeanFactoryUtils
                                .beanNamesForTypeIncludingAncestors(
                                    this.beanFactory, Object.class, true, false);
                    
                    for (String beanName : beanNames) {
                        if (!isEligibleBean(beanName)) {
                            continue;
                        }
 
                        Class<?> beanType = this.beanFactory.getType(beanName);
                        if (beanType == null) {
                            continue;
                        }
                        //判断是不是Aspect类 是否有@Aspect注解
                        if (this.advisorFactory.isAspect(beanType)) {
                            aspectNames.add(beanName);
                            AspectMetadata amd = 
                                new AspectMetadata(beanType, beanName);
                        if (amd.getAjType().getPerClause().getKind() 
                                == PerClauseKind.SINGLETON) {
                                //构建解析Aspect的工厂类
                                MetadataAwareAspectInstanceFactory factory =
                                        new BeanFactoryAspectInstanceFactory
                                                    (this.beanFactory, beanName);
                                //解析Aspect下的所有的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 {
                                if (this.beanFactory.isSingleton(beanName)) {
                                    throw new IllegalArgumentException();
                                }
                                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<>();
        //遍历所有的Aspect
        for (String aspectName : aspectNames) {
            //根据AspectName从缓存中获取对应的List<Advisor> 并加入advisors
            List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
            if (cachedAdvisors != null) {
                advisors.addAll(cachedAdvisors);
            }else {
                MetadataAwareAspectInstanceFactory factory
                                = this.aspectFactoryCache.get(aspectName);
                //如果是AspectJAdvisorFactory接口类型的实现类
                //直接调用getAdvisors 获取对应的List<Advisor> 加入 advisors
                advisors.addAll(this.advisorFactory.getAdvisors(factory));
            }
        }
        return advisors;
    }

我们可以看到,首先第一次调用这个buildAspectJAdvisors()方法时,这个aspectNames一定是个null,接着就会进入到这个if分支的处理中,首先从IOC容器中获取所有的bean,然后遍历依次处理每个bean。

在处理bean的时候,有两步非常重要的操作,

第一步就是通过advisorFactory.isAspect()找到所有加了@Aspect注解的类;

第二步就是通过this.advisorFactory.getAdvisors(factory)进一步找到切面类中的增强方法,并将增强方法构建为Advisor。

看下第二步this.advisorFactory.getAdvisors(factory)是怎么做的?

@Override
    public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
        Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
        String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
        validate(aspectClass);
 
        MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
                new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
​
        List<Advisor> advisors = new ArrayList<>();
        //获取所有的增强方法
        for (Method method : getAdvisorMethods(aspectClass)) {
            //构建InstantiationModelAwarePointcutAdvisorImpl实例
            Advisor advisor
                = getAdvisor(method, lazySingletonAspectInstanceFactory, 
                                                    advisors.size(), aspectName);
            if (advisor != null) {
                advisors.add(advisor);
            }
        }
 
        if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory
                                        .getAspectMetadata().isLazilyInstantiated()) {
            Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor
                                                    (lazySingletonAspectInstanceFactory);
            advisors.add(0, instantiationAdvisor);
        }
 
        for (Field field : aspectClass.getDeclaredFields()) {
            Advisor advisor = getDeclareParentsAdvisor(field);
            if (advisor != null) {
                advisors.add(advisor);
            }
        }
​
        return advisors;
    }
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
        final List<Method> methods = new ArrayList<>();
        ReflectionUtils.doWithMethods(
            //参数1:aspectClass:@Aspect注解的类
            aspectClass, 
            //参数2:MethodCallback
            method -> {
            //没有@Pointcut注解的方法 加入methods
            if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
                methods.add(method);
            }
        }, 
            //参数3:MethodFilter
            //(method -> !method.isBridge() && !method.isSynthetic() && 
            //                  method.getDeclaringClass() != Object.class);
            ReflectionUtils.USER_DECLARED_METHODS);
        if (methods.size() > 1) {
            methods.sort(METHOD_COMPARATOR);
        }
        return methods;
    }
public static void doWithMethods(Class<?> clazz, MethodCallback mc, @Nullable MethodFilter mf) {
        // 获取代理类class的所有的方法
        Method[] methods = getDeclaredMethods(clazz);
        for (Method method : methods) {
            /***
            调用!method.isBridge() && !method.isSynthetic() 
            过滤桥接方法和合成方法
            ***/
            //
            if (mf != null && !mf.matches(method)) {
                continue;
            }
            try {
                /***
                没有@Pointcut注解的方法 加入methods
                ***/
                mc.doWith(method);
            }
            catch (IllegalAccessException ex) {
                throw new IllegalStateException();
            }
        }
        //获取父类中的 方法
        if (clazz.getSuperclass() != null) {
            doWithMethods(clazz.getSuperclass(), mc, mf);
        }
        else if (clazz.isInterface()) {
            for (Class<?> superIfc : clazz.getInterfaces()) {
                doWithMethods(superIfc, mc, mf);
            }
        }
    }

第一个条件:!mf.matches(method);

public static final MethodFilter USER_DECLARED_METHODS
            =(method -> !method.isBridge() 
                    && !method.isSynthetic() 
                    && method.getDeclaringClass() != Object.class);

直接调用了Method对象的isBridge()方法和isSynthetic()方法来做的过滤,而这个isBridge()方法是用来判断当前方法是否为桥接方法,而isSynthetic()方法是用来判断当前方法是否为合成方法。

关于桥接方法和合成方法算是Java中的一个冷门知识了,简单来说,桥接方法和合成方法是编译器由于内部需要,编译器自己创建出来的方法,而不是我们程序员创建的方法。

!method.isBridge() && !method.isSynthetic() 这行代码在当前方法为非桥接方法且非合成方法时会返回true,说白了就是过滤出我们程序员创建的方法,排除掉那些编译器内部创建的乱七八糟的方法。

第二个条件:mc.doWith(method);

//没有@Pointcut注解的方法 加入methods
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
    methods.add(method);
}

说白了这个条件就是用来排除掉@Pointcut注解的pointcut() 方法的。

接下来遍历上面返回的非桥接方法和合成方法以及带有@Pointcut的方法再做一次过滤。

找出那些带有增强注解的方法:@Pointcut,@Around, @Before,@After,@AfterReturning,@AfterThrowing

由于@Pointcut修饰的方法已经被排除了所以只有5种增强的方法会被选中。

        //获取所有的增强方法
        for (Method method : getAdvisorMethods(aspectClass)) {
            //构建InstantiationModelAwarePointcutAdvisorImpl实例
            Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 
                                                        advisors.size(), aspectName);
            if (advisor != null) {
                advisors.add(advisor);
            }
        }
@Override
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,int declarationOrderInAspect, String aspectName) {
        
        validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
        AspectJExpressionPointcut expressionPointcut 
                            = getPointcut(candidateAdviceMethod, 
                                    aspectInstanceFactory
                                            .getAspectMetadata()
                                                    .getAspectClass());
    
        //如果不存在增强注解
        if (expressionPointcut == null) {
            return null;
        }
        //如果存在增强注解返回InstantiationModelAwarePointcutAdvisorImpl
        return new InstantiationModelAwarePointcutAdvisorImpl
                    (expressionPointcut, candidateAdviceMethod,
                    this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
    }
2.3.1.1.1查询增强方法

第一步:getPointcut()底层会依次在指定method上查找AspectJ的六种注解,分别是@Pointcut、@Around、@Before、@After、@AfterReturning、@AfterThrowing。

private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
        //获取方法上的增强注解
        AspectJAnnotation<?> aspectJAnnotation =
                AbstractAspectJAdvisorFactory
                        .findAspectJAnnotationOnMethod(candidateAdviceMethod);
        if (aspectJAnnotation == null) {
            return null;
        }
        //如果增强注解 存在那么解析增强注解上的切面表达式
        //@Around("pointCut()") 
        //@Around("execution(* tyrant.*.log(..))")
        AspectJExpressionPointcut ajexp =
                new AspectJExpressionPointcut
                            (candidateAspectClass, new String[0], new Class<?>[0]);
        //为返回的pointCut设置切面表达式
        ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
        if (this.beanFactory != null) {
            ajexp.setBeanFactory(this.beanFactory);
        }
        return ajexp;
    }

具体查找的话就是findAspectJAnnotationOnMethod方法的这行代码:

AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz)。

相当于又进行了1次过滤,判断是否是注解增强的方法。

protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
    //ASPECTJ_ANNOTATION_CLASSES是1个数组   
    //@Pointcut、@Around、@Before、@After、@AfterReturning、@AfterThrowing。
    for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
            AspectJAnnotation<?> foundAnnotation 
                        = findAnnotation(method, (Class<Annotation>) clazz);
            if (foundAnnotation != null) {
                return foundAnnotation;
            }
        }
        return null;
    }
2.3.1.1.2为增强方法构建Advisor

首先就是调用getPointcut()方法来获取method上的切点信息AspectJExpressionPointcut。

AspectJExpressionPointcut切点信息包含了增强方法上的增强注解的切面表达式。

接下来为增强方法构建Advisor。构建一个InstantiationModelAwarePointcutAdvisorImpl实例。

最后将这个实例返回。

return new InstantiationModelAwarePointcutAdvisorImpl
                //pointcut包含增强方法的切面表达式
                (expressionPointcut, 
                 //增强方法
                 candidateAdviceMethod,
                    this, aspectInstanceFactory, 
                 declarationOrderInAspect, aspectName);
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
​
    this.declaredPointcut = declaredPointcut;
    this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
    this.methodName = aspectJAdviceMethod.getName();
    this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
    this.aspectJAdviceMethod = aspectJAdviceMethod;
    this.aspectJAdvisorFactory = aspectJAdvisorFactory;
    this.aspectInstanceFactory = aspectInstanceFactory;
    this.declarationOrder = declarationOrder;
    this.aspectName = aspectName;
​
    if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
        Pointcut preInstantiationPointcut = Pointcuts.union(
                aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
        this.pointcut = new PerTargetInstantiationModelPointcut(
                this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
        this.lazy = true;
    }else {
        //走这里
        this.pointcut = this.declaredPointcut;
        this.lazy = false;
        this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
    }
}

这里直接通过构造方法的方式,将增强方法 candidateAdviceMethod 和 切点 expressionPointcut 等关键信息注入到了InstantiationModelAwarePointcutAdvisorImpl类的实例中。

Advisor中包含了增强方法 candidateAdviceMethod 和 切点 expressionPointcut 等关键信息。

接下来是将构建的Advisors放入缓存,这一步不重要。

经过这个findCandidateAdvisors()方法的处理,那么IOC容器中所有的增强都会被放入到advisors集合中,最后作为结果返回也就是说到目前为止:

List<Advisor> candidateAdvisors = findCandidateAdvisors()

这行代码已经执行完毕了。

此时返回的这个candidateAdvisors中就包含了IOC容器中所有切面类中的所有增强Advisor,那此时我们总不能无脑让这些增强都适用于当前bean吧?

这个肯定是不对的,有可能我们这个bean完全都不满足某一个切面类的切点表达式,对吧?

那接下来该怎么做呢?

其实很简单,那就是从所有切面类的所有增强Advisor中,找到与当前bean相匹配的增强Advisors。

也就是执行这行代码:

List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName)

这个findAdvisorsThatCanApply()方法会使用增强Advisor中的切点表达式与当前bean中的方法做匹配。

从而找到与当前bean匹配的增强Advisor。

2.3.1.2findAdvisorsThatCanApply

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
        if (candidateAdvisors.isEmpty()) {
            return candidateAdvisors;
        }
        List<Advisor> eligibleAdvisors = new ArrayList<>();
        for (Advisor candidate : candidateAdvisors) {
        //引介增强
        if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
                eligibleAdvisors.add(candidate);
            }
        }
        boolean hasIntroductions = !eligibleAdvisors.isEmpty();
        for (Advisor candidate : candidateAdvisors) {
            //引介增强在上面处理过 直接跳过
            if (candidate instanceof IntroductionAdvisor) {
                continue;
            }
            //判断普通增强
            if (canApply(candidate, clazz, hasIntroductions)) {
                eligibleAdvisors.add(candidate);
            }
        }
        return eligibleAdvisors;
    }

findAdvisorsThatCanApply()方法的作用,就是用来完成bean和candidateAdvisors之间的匹配的,最后会将bean匹配到的增强advisors作为出参进行返回。

我们可以看到,这里有两块处理逻辑,我们发现这2块逻辑都会往最终结果eligibleAdvisors中添加元素。

其中第一块逻辑,也就是第一个for循环中,是当 candidate instanceof IntroductionAdvisor 为true时,就会调用canApply(candidate, clazz)方法进行匹配

而第二块逻辑,也就是第二个for循环中,是当 candidate instanceof IntroductionAdvisor 为false时,会调用canApply(candidate, clazz, hasIntroductions)方法进行匹配。

增强还有分类?普通增强、引介增强都是什么?

IntroductionAdvisor其实就是一个接口,继承了Advisor接口。

其实这个IntroductionAdvisor代表了一种增强,我们一般称为“引介增强”,这种引介增强控制的是类级别,控制粒度是比较粗的,所以一般我们不常用,其实candidate instanceof IntroductionAdvisor这行代码,说白了就是用来判断candidate是不是引介增强的。

那现在问题来了,这里的candidate,也就是candidateAdvisors数组中的Advisor到底是不是引介增强呢?

说白了就是有没有实现IntroductionAdvisor接口

没有,因为我们的Advisor其实是InstantiationModelAwarePointcutAdvisorImpl类的一个实例。

因为构建这个Advisor的时候是直接通过InstantiationModelAwarePointcutAdvisorImpl类的构造方法来完成的。

那现在就好办了,我们直接来看下InstantiationModelAwarePointcutAdvisorImpl类的继承关系不就知道了吗?此时InstantiationModelAwarePointcutAdvisorImpl类的继承关系如下图:

image.png

我们可以看到,PointcutAdvisor接口(普通增强)和IntroductionAdvisor接口(引介增强)都继承了Advisor接口, 而InstantiationModelAwarePointcutAdvisorImpl类实现的是PointcutAdvisor接口,而不是IntroductionAdvisor接口,也就是说当前这个candidate并不是引介增强,而是一个普通增强。

所以此时candidate instanceof IntroductionAdvisor这行代码会返回false,接着就会执行普通增强的匹配逻辑。所以此时就会来执行这个canApply(candidate, clazz, hasIntroductions)方法了。

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
    //如果是引介增强 那么需要对类级别进行匹配
    //具体是使用切面表达式
    if (advisor instanceof IntroductionAdvisor) {
        return ((IntroductionAdvisor)advisor)
                        .getClassFilter().matches(targetClass);
    //如果是普通增强  
    }else if (advisor instanceof PointcutAdvisor) {
        PointcutAdvisor pca = (PointcutAdvisor) advisor;
        return canApply(pca.getPointcut(), targetClass, hasIntroductions);
    }
    else {
        return true;
    }
}

关于普通增强,这里再补充一点,那就是大家还记得吗?我们在定义切面的时候可是指定了切点表达式的哦,利用切点表达式我们可以匹配到方法级别,由于普通增强控制的粒度更细,所以我们一般会使用这种PointcutAdvisor类型的增强,也就是普通增强。

来跟踪下目标类与切点表达式的匹配过程

接下来,我们就来看下普通增强到底是怎么进行匹配的,此时我们点进去canApply(candidate, clazz, hasIntroductions)方法,就会看到如下代码:

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
        Assert.notNull(pc, "Pointcut must not be null");
        //首先进行类级别的匹配
        //如果是AOP增强:这个AspectJExpressionPointcut是不是很眼熟
        //Advisor pc = AspectJExpressionPointcut 
        //对应的classfilter是AspectJExpressionPointcut,
        //需要先使用切面表达式和类匹配
    
        //如果是事务增强的Advisor pc = StaticMethodMatcherPointcut
        //对应的classfilter是ClassFilter.TRUE,直接返回true
        //不需要类级别的匹配
        //因为
        if (!pc.getClassFilter().matches(targetClass)) {
            return false;
        }
        
        //从PointcutAdvisor中拿Pointcut
        //从Pointcut拿的方法匹配器
        MethodMatcher methodMatcher = pc.getMethodMatcher();
        if (methodMatcher == MethodMatcher.TRUE) {
            return true;
        }
​
        IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
        if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
            introductionAwareMethodMatcher
                    = (IntroductionAwareMethodMatcher) methodMatcher;
        }
​
        Set<Class<?>> classes = new LinkedHashSet<>();
        if (!Proxy.isProxyClass(targetClass)) {
            classes.add(ClassUtils.getUserClass(targetClass));
        }
        classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
        //再进行方法级别的匹配
        //每一个advisor的匹配器和class的所有方法匹配 只要匹配到就加入eligible集合
        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;
    }

我们可以看到,这里分别在类级别和方法级别进行匹配,首先会调用pc.getClassFilter().matches(targetClass)进行类级别的匹配,说白了就是使用切点表达式和目标类进行匹配,如果在类级别都不满足切点表达式的话,那么就没必要进一步去匹配方法了。

只有当类级别满足切点表达式之后,才会进行方法级别的匹配,此时就会获取目标类中的方法,然后依次判断每个方法是否与Advisor中的切点表达式正常匹配。如果匹配加入advisor集合。

只要目标类中有一个方法可以和切点表达式匹配上,那么需要将这个Advisor加入eligibleAdvisors。

只要目标类中有一个方法可以和切点表达式匹配上,那么需要将这个Advisor加入eligibleAdvisors。

只要目标类中有一个方法可以和切点表达式匹配上,那么需要将这个Advisor加入eligibleAdvisors。

假设A方法可以和切面表达式匹配那么对应的advisor就会加入eligibleAdvisors集合

所以这就要求我们在调用时,需要再次做精确匹配,因为由方法A筛选符合条件的advisor对于方法B可能不适用。

那么现在的重点,就是目标类方法和切点表达式是怎么进行匹配的?

这一块我们还需要再深入探索一下,此时我们点进去方法来看一下,代码如下

introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions):

@Override
public boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions) {
    obtainPointcutExpression();
    ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);
    if (shadowMatch.alwaysMatches()) {
        return true;
    }
    else if (shadowMatch.neverMatches()) {
        return false;
    }
    else {
        if (hasIntroductions) {
            return true;
        }
        RuntimeTestWalker walker = getRuntimeTestWalker(shadowMatch);
        return (!walker.testsSubtypeSensitiveVars() || 
                        walker.testTargetInstanceOfResidue(targetClass));
    }
}

我们可以看到这里直接调用getTargetShadowMatch(method, targetClass)方法获取了匹配结果shadowMatch,而如果shadowMatch.alwaysMatches()方法的结果为true的话,那么就说明这个类是需要创建代理的。

因此核心匹配的逻辑在这个getTargetShadowMatch(method, targetClass)方法中,那还有啥好说的,我们继续跟进呗,此时我们会看到下面的代码:

private ShadowMatch getTargetShadowMatch(Method method, Class<?> targetClass) {
    Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
    if (targetMethod.getDeclaringClass().isInterface()) {
        Set<Class<?>> ifcs = ClassUtils.getAllInterfacesForClassAsSet(targetClass);
        if (ifcs.size() > 1) {
            try {
                Class<?> compositeInterface = ClassUtils.createCompositeInterface(
                        ClassUtils.toClassArray(ifcs), targetClass.getClassLoader());
                targetMethod = ClassUtils.getMostSpecificMethod(targetMethod, compositeInterface);
            }
            catch (IllegalArgumentException ex) {

            }
        }
    }
    return getShadowMatch(targetMethod, method);
}

主要就是调用了另外一个方法getShadowMatch(targetMethod, method)。

那我们继续跟进getShadowMatch(targetMethod, method)方法

private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {
    // Avoid lock contention for known Methods through concurrent access...
    ShadowMatch shadowMatch = this.shadowMatchCache.get(targetMethod);
    if (shadowMatch == null) {
        synchronized (this.shadowMatchCache) {
            // Not found - now check again with full lock...
            PointcutExpression fallbackExpression = null;
            shadowMatch = this.shadowMatchCache.get(targetMethod);
            if (shadowMatch == null) {
                Method methodToMatch = targetMethod;
                try {
                    try {
                        shadowMatch = obtainPointcutExpression()
                                            .matchesMethodExecution(methodToMatch);
                    }catch (ReflectionWorldException ex) {
​
                        try {
                            fallbackExpression = getFallbackPointcutExpression
                                                    (methodToMatch.getDeclaringClass());
                            if (fallbackExpression != null) {
                                shadowMatch = fallbackExpression
                                                .matchesMethodExecution(methodToMatch);
                            }
                        }catch (ReflectionWorldException ex2) {
                            fallbackExpression = null;
                        }
                    }
                    if (targetMethod != originalMethod
                        && (shadowMatch == null ||(shadowMatch.neverMatches() 
                          && Proxy.isProxyClass(targetMethod.getDeclaringClass())))) {

                        methodToMatch = originalMethod;
                        try {
                            shadowMatch = obtainPointcutExpression()
                                            .matchesMethodExecution(methodToMatch);
                        }catch (ReflectionWorldException ex) {
                            try {
                                fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
                                if (fallbackExpression != null) {
                                    shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
                                }
                            }catch (ReflectionWorldException ex2) {
                                fallbackExpression = null;
                            }
                        }
                    }
                }catch (Throwable ex) {
                    // Possibly AspectJ 1.8.10 encountering an invalid signature
                    logger.debug("PointcutExpression matching rejected target method", ex);
                    fallbackExpression = null;
                }
                if (shadowMatch == null) {
                    shadowMatch = new ShadowMatchImpl(org.aspectj.util.FuzzyBoolean.NO, null, null, null);
                }
                else if (shadowMatch.maybeMatches() && fallbackExpression != null) {
                    shadowMatch = new DefensiveShadowMatch(shadowMatch,
                            fallbackExpression.matchesMethodExecution(methodToMatch));
                }
                this.shadowMatchCache.put(targetMethod, shadowMatch);
            }
        }
    }
    return shadowMatch;
}

此时我们可以看到,刚进来这个方法时,会看一下缓存中有没有shadowMatch,第一次进来的话肯定是没有的,所以就会进来这个if分支的代码,那么此时就会执行非常核心的一块代码,

就是shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch)这行代码。

首先我们来看下这个obtainPointcutExpression()方法是干嘛的,代码如下:

private PointcutExpression obtainPointcutExpression() {
        if (getExpression() == null) {
            throw new IllegalStateException("");
        }
        if (this.pointcutExpression == null) {
            this.pointcutClassLoader = determinePointcutClassLoader();
            this.pointcutExpression = 
                    buildPointcutExpression(this.pointcutClassLoader);
        }
        return this.pointcutExpression;
    }

我们可以看到,原来在这个obtainPointcutExpression()方法中,进行了AspectJ切点表达式的解析,比如我们日志切面类中的切点表达式execution(public * com.ruyuan.aop.service.ProductServiceImpl.*(..)),最后解析完切点表达式之后,会将切点表达式构建为一个PointcutExpressionImpl类的实例,也就是说obtainPointcutExpression()方法返回的其实就是一个PointcutExpressionImpl类的实例。

刚才我们执行到了

shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch)

这行代码,现在obtainPointcutExpression()方法返回了一个PointcutExpressionImpl类的实例,那么接下来就会调用PointcutExpressionImpl类的matchesMethodExecution(methodToMatch)来完成切点表达式和目标类的匹配。

正当我们进入PointcutExpressionImpl类一探究竟时,我们发现这个PointcutExpressionImpl类竟然是aspectj包下的类,也就是说方法匹配这块是由aspectj包完成的,而不是Spring来完成的,Spring只是借助了人家aspectj现成的功能罢了。

那么aspectj是在哪里被引入了呢?

其实Spring是在spring-aspects中引入了aspectjweaver的依赖。

AOP代理的创建:aspectj是怎么来完成方法级别精准匹配的?

现在我们知道obtainPointcutExpression()方法返回的是一个PointcutExpressionImpl类的实例,那么接下来就会调用PointcutExpressionImpl类的matchesMethodExecution(methodToMatch)方法,来完成切点表达式和目标类的匹配。

那我们现在就来看下PointcutExpressionImpl类的matchesMethodExecution(methodToMatch)方法吧。

此时我们会看到如下代码:

代码所在类的全限定类名:org.aspectj.weaver.internal.tools.PointcutExpressionImpl

public ShadowMatch matchesMethodExecution(Method aMethod) {
    // 从这里进去匹配
    ShadowMatch match = matchesExecution(aMethod);
    if (MATCH_INFO && match.maybeMatches()) {
        System.out.println("MATCHINFO: method execution match on '" + aMethod + "' for '" + this.expression + "': "
                + (match.alwaysMatches() ? "YES" : "MAYBE"));
    }
    return match;
}
​
private ShadowMatch matchesExecution(Member aMember) {
    // 这行代码可以暂时忽略
    Shadow s = ReflectionShadow.makeExecutionShadow(world, aMember, this.matchContext);
    // 这里是重点
    ShadowMatchImpl sm = getShadowMatch(s);
    sm.setSubject(aMember);
    sm.setWithinCode(null);
    sm.setWithinType(aMember.getDeclaringClass());
    return sm;
}
​
private ShadowMatchImpl getShadowMatch(Shadow forShadow) {
    // 切点表达式匹配
    org.aspectj.util.FuzzyBoolean match = pointcut.match(forShadow);
    // 省略部分代码
    return sm;
}

通过上边的代码,我们可以看到在matchesMethodExecution()方法中又调用了matchesExecution(aMethod)方法来完成匹配,而matchesExecution(aMethod)方法中的重点是getShadowMatch(s)方法

在getShadowMatch(s)方法中,调用了pointcut.match(forShadow)完成了切点表达式的匹配,而pointcut.match(forShadow)的代码如下:

代码所在类的全限定类名:org.aspectj.weaver.patterns.Pointcut

public final FuzzyBoolean match(Shadow shadow) {
    // 省略部分代码
    if (shadow.getKind().isSet(couldMatchKinds())) {
        // 这里开始匹配
        ret = matchInternal(shadow);
    } else {
        ret = FuzzyBoolean.NO;
    }
    // 省略部分代码
    return ret;
}

通过上边的代码,我们可以看到,这里又继续调用了matchInternal(shadow)方法完成了匹配,我们继续往下深入,此时matchInternal(shadow)代码如下:

代码所在类的全限定类名:org.aspectj.weaver.patterns.KindedPointcut

@Override
protected FuzzyBoolean matchInternal(Shadow shadow) {
    if (shadow.getKind() != kind) {
        return FuzzyBoolean.NO;
    }
​
    if (shadow.getKind() == Shadow.SynchronizationLock && kind == Shadow.SynchronizationLock) {
        return FuzzyBoolean.YES;
    }
    if (shadow.getKind() == Shadow.SynchronizationUnlock && kind == Shadow.SynchronizationUnlock) {
        return FuzzyBoolean.YES;
    }
​
    // signature.matches() 签名匹配,核心方法
    if (!signature.matches(shadow.getMatchingSignature(), 
                          shadow.getIWorld(), this.kind == Shadow.MethodCall)) {
        // 省略部分代码
        return FuzzyBoolean.NO;
    }
​
    return FuzzyBoolean.YES;
}

通过上边的代码,我们可以看到,在matchInternal()方法刚进来时先做了一些判断,然后接着又调用了signature.matches(),从这个方法的名字来看,是对签名进行匹配,看起来离匹配的核心逻辑已经非常近了,接下来我们点进去看下这个signature.matches()的代码,大家看这里

代码所在类的全限定类名:org.aspectj.weaver.patterns.SignaturePattern

@Override
public boolean matches(Member joinPointSignature, World world, boolean allowBridgeMethods) {
    // 省略部分代码
    while (candidateMatches.hasNext()) {
        JoinPointSignature aSig = candidateMatches.next();
        // System.out.println(aSig);
        // 精确匹配
        FuzzyBoolean matchResult = matchesExactly(aSig, world, allowBridgeMethods, subjectMatch);
        if (matchResult.alwaysTrue()) {
            return true;
        } else if (matchResult.alwaysFalse()) {
            return false;
        }
        // 省略部分代码
    }
    return false;
}

private FuzzyBoolean matchesExactly(JoinPointSignature aMember, World inAWorld, boolean allowBridgeMethods, boolean subjectMatch) {
    // 省略部分代码
    FuzzyBoolean matchesIgnoringAnnotations = FuzzyBoolean.YES;
    if (kind == Member.STATIC_INITIALIZATION) {
        // 静态初始化类型的匹配
        matchesIgnoringAnnotations = matchesExactlyStaticInitialization(aMember, inAWorld);
    } else if (kind == Member.FIELD) {
        // 属性精确匹配
        matchesIgnoringAnnotations = matchesExactlyField(aMember, inAWorld);
    } else if (kind == Member.METHOD) {
        // 方法精确匹配,因为我们就是要匹配方法,所以当然会走这里
        matchesIgnoringAnnotations = matchesExactlyMethod(aMember, inAWorld, subjectMatch);
    } else if (kind == Member.CONSTRUCTOR) {
        // 构造方法精确匹配
        matchesIgnoringAnnotations = matchesExactlyConstructor(aMember, inAWorld);
    }
    if (matchesIgnoringAnnotations.alwaysFalse()) {
        return FuzzyBoolean.NO;
    }
    // 省略部分代码
}

在这个matches()方法中,最最核心的是调用了matchesExactly()方法,从方法名matchesExactly()来看,它的作用就是做精确匹配的。

当我们看到matchesExactly()方法的代码后,我们发现了新大陆,在这个方法中,它进一步区分了当前你要做的是属性的精确匹配,还是方法的精确匹配,又或者是构造方法的精确匹配.

我们现在要做的当然是方法级别的精确匹配啦,所以就会进入if (kind == Member.METHOD)这个if分支,接着就会调用matchesExactlyMethod()方法来完成方法级别的精确匹配。

此时我们迫不及待的点开matchesExactlyMethod()方法,方法中的代码也随之展示在了我们的眼前

代码所在类的全限定类名:org.aspectj.weaver.patterns.SignaturePattern

/**
 * Matches on name, declaring type, return type, parameter types, throws types
 */
private FuzzyBoolean matchesExactlyMethod(JoinPointSignature aMethod, World world, boolean subjectMatch) {
    // 判断方法参数是够匹配,不匹配返回NO
    if (parametersCannotMatch(aMethod)) {
        // System.err.println("Parameter types pattern " + parameterTypes + " pcount: " + aMethod.getParameterTypes().length);
        return FuzzyBoolean.NO;
    }
    // OPTIMIZE only for exact match do the pattern match now? Otherwise defer it until other fast checks complete?
    // 判断方法名称是够匹配,不匹配返回NO
    if (!name.matches(aMethod.getName())) {
        return FuzzyBoolean.NO;
    }
    // Check the throws pattern
    // 判断方法抛出异常是够匹配,不匹配返回NO
    if (subjectMatch && !throwsPattern.matches(aMethod.getExceptions(), world)) {
        return FuzzyBoolean.NO;
    }
​
    // '*' trivially matches everything, no need to check further
    if (!declaringType.isStar()) {
        if (!declaringType.matchesStatically(aMethod.getDeclaringType().resolve(world))) {
            return FuzzyBoolean.MAYBE;
        }
    }
​
    // '*' would match any return value
    // 判断返回值类型是够匹配,不匹配返回NO
    // 如果切点表达式返回值类型为*,则表示可以匹配任何类型,就没必要进行下边的匹配
    // 而如果切点表达式返回值类型不是*,则对返回值类型进行匹配
    if (!returnType.isStar()) {
        boolean b = returnType.isBangVoid();
        if (b) {
            String s = aMethod.getReturnType().getSignature();
            if (s.length() == 1 && s.charAt(0) == 'V') {
                // it is void, so not a match
                return FuzzyBoolean.NO;
            }
        } else {
            if (returnType.isVoid()) {
                String s = aMethod.getReturnType().getSignature();
                if (s.length() != 1 || s.charAt(0) != 'V') {
                    // it is not void, so not a match
                    return FuzzyBoolean.NO;
                }
            } else {
                if (!returnType.matchesStatically(aMethod.getReturnType().resolve(world))) {
                    // looking bad, but there might be parameterization to consider...
                    if (!returnType.matchesStatically(aMethod.getGenericReturnType().resolve(world))) {
                        // ok, it's bad.
                        return FuzzyBoolean.MAYBE;
                    }
                }
            }
        }
    }
​
    // The most simple case: pattern is (..) will match anything
    // 如果切点表达式方法参数只配置了一个参数,且这个参数是..
    // 那么就表示可以匹配任何参数类型,此时直接返回YES
    if (parameterTypes.size() == 1 && parameterTypes.get(0).isEllipsis()) {
        return FuzzyBoolean.YES;
    }
​
    // 如果切点表达式配置的参数个数和目标方法的参数个数不相等时,那么直接返回NO
    if (!parameterTypes.canMatchSignatureWithNParameters(aMethod.getParameterTypes().length)) {
        return FuzzyBoolean.NO;
    }
​
    // OPTIMIZE both resolution of these types and their annotations should be deferred - just pass down a world and do it lower
    // down
    // ResolvedType[] resolvedParameters = world.resolve(aMethod.getParameterTypes());ResolvableTypeList rtl = new ResolvableTypeList(world, aMethod.getParameterTypes());
    // Only fetch the parameter annotations if the pointcut is going to be matching on them
    // 当方法参数上加了注解时,就需要来匹配参数注解
    ResolvedType[][] parameterAnnotationTypes = null;
    if (isMatchingParameterAnnotations()) {
        parameterAnnotationTypes = aMethod.getParameterAnnotationTypes();
        if (parameterAnnotationTypes != null && parameterAnnotationTypes.length == 0) {
            parameterAnnotationTypes = null;
        }
    }
​
    // 对方法参数的类型进行匹配
    if (!parameterTypes.matches(rtl, TypePattern.STATIC, parameterAnnotationTypes).alwaysTrue()) {
        // It could still be a match based on the generic sig parameter types of a parameterized type
        if (!parameterTypes.matches(new ResolvableTypeList(world, aMethod.getGenericParameterTypes()), TypePattern.STATIC,
                parameterAnnotationTypes).alwaysTrue()) {
            return FuzzyBoolean.MAYBE;
            // It could STILL be a match based on the erasure of the parameter types??
            // to be determined via test cases...
        }
    }
​
    // check that varargs specifications match
    // 对可变参数的处理,检查可变参数是否匹配
    if (!matchesVarArgs(aMethod, world)) {
        return FuzzyBoolean.MAYBE;
    }
​
    // passed all the guards..
    return FuzzyBoolean.YES;
}

aspectj匹配方法的套路,简单说就是,aspectj会根据切点表达式的配置,分别与目标方法的方法参数、方法名字、方法返回参数、方法抛出异常进行匹配,如果都满足的话,那么就表示当前目标方法是满足切点表达式的,也同时说明目标方法所在的类是需要设置代理的!

匹配的时候是一个for循环,也就是目标类会和所有的增强Advisors都匹配一遍,最终将目标类匹配上的增强Advisor给放到这个eligibleAdvisors集合中作为结果返回。

只要目标类中任意一个方法与增强中的切点表达式匹配上,代表当前增强Advisor是适合这个目标类的。

需要加入eligibleAdvisors集合中。

同时也表示这个目标类是需要设置为代理的。

同时我们返回的advisor集合中的实例有2种类型

切面:InstantiationModelAwarePointcutAdvisor
事务:BeanFactoryTransactionAttributeSourceAdvisor

到这里为止,获取目标类匹配的增强逻辑就分析完毕了,下一步就要利用获取到的这些增强来创建动态代理了!

总结:判断是否需要代理,获取可用Advisors

一.获取所有的advisor,方式有2种:

1.根据type

2.从Aspect类中的方法解析:

找到所有的Aspect类,遍历Aspect类所有的方法,过滤掉非合成非桥接方法和非@Pointcut注解修饰的方法。

进一步判断是否是增强方法,如果是说明是符合条件的增强方法,解析增强方法的切面表达式,

并使用切面表达式构建1个AspectJExpressionPointcut返回。

使用增强方法和AspectJExpressionPointcut构建InstantiationModelAwarePointcutAdvisorImpl实例。

二.为代理类选择可用的advisor。

外层for循环advisors{
​
    内层循环代理类所有的方法{
    
        1.先使用advisor的切面表达式和类匹配
​
        2.在使用切面表达式和方法匹配
​
        3.如果有任意一个方法和advisor能匹配上
​
        4.那么这个advisor就是可用的。
​
        5.由于A方法匹配的advisor对于B方法可能不适用!
​
        6.所以在具体代理类的方法调用时,需要做进一步的判断。
    }
}