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


highlight: arduino-light

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

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

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

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

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

SpringAop示例代码

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

}

```

```java 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----");
}

} ```

```java package aop;

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

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

} ```

```java package aop;

import org.springframework.stereotype.Component;

@Component
public interface LogService {

      void print();
}

```

```java

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

java @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

java 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的时候可以被拦截调用。

```java 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

```java protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction) () -> { 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的后置处理方法时,生成的代理对象。

java @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

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

2.AbstractAutoProxyCreator#wrapIfNecessary

```md 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 ```

```java 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等是跟切面相关的,不需要代理 java 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

```java protected boolean shouldSkip(Class> beanClass, String beanName) { return AutoProxyUtils.isOriginalInstance(beanName, beanClass); }

```

java 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

```java @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 buildAspectJAdvisors() { //里面只有一个aop List aspectNames = this.aspectBeanNames; ​ if (aspectNames == null) { synchronized (this) { aspectNames = this.aspectBeanNames; if (aspectNames == null) { List 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 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 advisors = new ArrayList<>(); //遍历所有的Aspect for (String aspectName : aspectNames) { //根据AspectName从缓存中获取对应的List 并加入advisors List cachedAdvisors = this.advisorsCache.get(aspectName); if (cachedAdvisors != null) { advisors.addAll(cachedAdvisors); }else { MetadataAwareAspectInstanceFactory factory                   = this.aspectFactoryCache.get(aspectName); //如果是AspectJAdvisorFactory接口类型的实现类 //直接调用getAdvisors 获取对应的List 加入 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 getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) { Class> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName(); validate(aspectClass);

MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
            new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

​ List 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。

java 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\

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

java 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实例。

最后将这个实例返回。

java return new InstantiationModelAwarePointcutAdvisorImpl //pointcut包含增强方法的切面表达式 (expressionPointcut,                 //增强方法                 candidateAdviceMethod, this, aspectInstanceFactory,                 declarationOrderInAspect, aspectName);

java 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\

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

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

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

那接下来该怎么做呢?

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

也就是执行这行代码:

List\

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

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

2.3.1.2findAdvisorsThatCanApply

java 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)方法了。

java 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 > 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):

java @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)方法中,那还有啥好说的,我们继续跟进呗,此时我们会看到下面的代码:

```java private ShadowMatch getTargetShadowMatch(Method method, Class> targetClass) { Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass); if (targetMethod.getDeclaringClass().isInterface()) { Set > 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()方法是干嘛的,代码如下:

java 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

java 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

java 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

java @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

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

java 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

java /** * 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。

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
java.lang.NullPointerException: null at com.datech.web.controller.system.TbappController.remove(TbappController.java:667) at com.datech.web.controller.system.TbappController$$FastClassBySpringCGLIB$$ea1c3ba.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:55) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) at org.apache.shiro.spring.security.interceptor.AopAllianceAnnotationsAuthorizingMethodInterceptor$1.proceed(AopAllianceAnnotationsAuthorizingMethodInterceptor.java:82) at org.apache.shiro.authz.aop.AuthorizingMethodInterceptor.invoke(AuthorizingMethodInterceptor.java:39) at org.apache.shiro.spring.security.interceptor.AopAllianceAnnotationsAuthorizingMethodInterceptor.invoke(AopAllianceAnnotationsAuthorizingMethodInterceptor.java:115) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691) at com.datech.web.controller.system.TbappController$$EnhancerBySpringCGLIB$$b3b02033.remove(<generated>) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
07-14

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值