Spring Aop初始化源码分析

共 27517字,需浏览 56分钟

 ·

2021-03-26 08:37

点击上方蓝色字体,选择“标星公众号”

优质文章,第一时间送达

1 工程简介


1.1 pom

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <spring.version>5.2.8.RELEASE</spring.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.20</version>
        </dependency>
        <!-- 日志相关依赖 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.10</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.1.2</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.1.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>

1.2 AopConfig

@Configuration
@EnableAspectJAutoProxy
@Aspect
public class AopConfig {

    /**
     * 声明切点
     */
    @Pointcut("execution(* com.rosh.service.*.*(..))")
    public void pointCut() {

    }

    @Around("pointCut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("==============调用前=================");
        Object proceed = proceedingJoinPoint.proceed();
        System.out.println("==============调用后=================");
        return proceed;
    }


}


1.3 StudentService

@Service
public class StudentService {

    public void addStudent() {
        System.out.println("添加学生");
    }


}


1.4 RoshTest

public class RoshTest {

    @Test
    public void mainTest(){

        AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext("com.rosh");

        StudentService studentService = (StudentService) applicationContext.getBean("studentService");

        studentService.addStudent();

    }

}


1.5 运行结果


2 @EnableAspectJAutoProxy作用

描述:开启Spring AOP功能。


(1) IOC中加入AspectJAutoProxyRegistrar.class

(2) 注册 AnnotationAwareAspectJAutoProxyCreator.class

3 AnnotationAwareAspectJAutoProxyCreator.class 源码分析

描述:该类是AOP核心类。该类实现了BeanPostProcessor接口,说明在bean初始化时,进行后置加强。

该类作用是,当bean初始化时,被该类后置加强:

(1) 查找有效的advisor列表。(advisor=advice+pointCut)
(2) 匹配当前bean,是否在pointCut表达式范围,匹配方法是否需要加强,把匹配到的advisor列表返回。
(3) 根据有效的advisor列表创建代理对象、 


3.1 后置加强逻辑

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

3.2 wrapIfNecessary方法

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
   return bean;
  }
  if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
   return bean;
  }
  if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
   this.advisedBeans.put(cacheKey, Boolean.FALSE);
   return bean;
  }

  // Create proxy if we have advice.
  /**
   * 【1】获取当前bean有效的Advisor,Advisor = advice + pointCut
   */
  Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

  if (specificInterceptors != DO_NOT_PROXY) {
   this.advisedBeans.put(cacheKey, Boolean.TRUE);

   /**
    * 【2】创建代理对象
    */
   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;
 }

3.3 getAdvicesAndAdvisorsForBean 方法解析

    @Override
 @Nullable
 protected Object[] getAdvicesAndAdvisorsForBean(
   Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

  /**
   * 查找Advisor
   */
  List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
  if (advisors.isEmpty()) {
   return DO_NOT_PROXY;
  }
  return advisors.toArray();
 }

描述:该方法获取有效的Advisor,主要作用,发现所有的advisor其次匹配当前bean。

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {

  /**
   * 【1】找到工程中所有Advisor(解析带有@Aspect注解类生成Advisor对象)
   */
  List<Advisor> candidateAdvisors = findCandidateAdvisors();

  /**
   * 【2】 匹配当前类
   */
  List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
  extendAdvisors(eligibleAdvisors);
  if (!eligibleAdvisors.isEmpty()) {
   eligibleAdvisors = sortAdvisors(eligibleAdvisors);
  }
  return eligibleAdvisors;
 }

3.3.1 findCandidateAdvisors

作用:查找所有的advisor。

@Override
 protected List<Advisor> findCandidateAdvisors() {
  // Add all the Spring advisors found according to superclass rules.
  //找到所有的Advisor
  List<Advisor> advisors = super.findCandidateAdvisors();
  // Build Advisors for all AspectJ aspects in the bean factory.

  /**
   * 创建候选切面 对@Aspect注解进行处理
   */
  if (this.aspectJAdvisorsBuilder != null) {
   advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
  }
  return advisors;
 }

核心方法:buildAspectJAdvisors()

public List<Advisor> buildAspectJAdvisors() {
  List<String> aspectNames = this.aspectBeanNames;

  if (aspectNames == null) {
   synchronized (this) {
    aspectNames = this.aspectBeanNames;
    if (aspectNames == null) {
     List<Advisor> advisors = new ArrayList<>();
     aspectNames = new ArrayList<>();

     /**
      * 从spring 中获取所有的类
      */
     String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
       this.beanFactory, Object.class, truefalse);
     for (String beanName : beanNames) {
      if (!isEligibleBean(beanName)) {
       continue;
      }
      // We must be careful not to instantiate beans eagerly as in this case they
      // would be cached by the Spring container but would not have been weaved.

      /**
       *  获取beanName 的class
       */
      Class<?> beanType = this.beanFactory.getType(beanName);
      if (beanType == null) {
       continue;
      }

      /**
       *  判断类上是否有@Aspect注解
       */
      if (this.advisorFactory.isAspect(beanType)) {
       aspectNames.add(beanName);
       AspectMetadata amd = new AspectMetadata(beanType, beanName);
       if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {

        //创建获取有@Aspect注解类的实例工厂,负责获取有@Aspect注解的实例
        MetadataAwareAspectInstanceFactory factory =
          new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);

        //创建切面Advisor对象
        List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
        if (this.beanFactory.isSingleton(beanName)) {
         this.advisorsCache.put(beanName, classAdvisors);
        }
        else {
         this.aspectFactoryCache.put(beanName, factory);
        }
        advisors.addAll(classAdvisors);
       }
       else {
        // Per target or per this.
        if (this.beanFactory.isSingleton(beanName)) {
         throw new IllegalArgumentException("Bean with name '" + beanName +
           "' is a singleton, but aspect instantiation model is not singleton");
        }
        MetadataAwareAspectInstanceFactory factory =
          new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
        this.aspectFactoryCache.put(beanName, factory);
        advisors.addAll(this.advisorFactory.getAdvisors(factory));
       }
      }
     }
     this.aspectBeanNames = aspectNames;
     return advisors;
    }
   }
  }

  if (aspectNames.isEmpty()) {
   return Collections.emptyList();
  }
  List<Advisor> advisors = new ArrayList<>();
  for (String aspectName : aspectNames) {
   List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
   if (cachedAdvisors != null) {
    advisors.addAll(cachedAdvisors);
   }
   else {
    MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
    advisors.addAll(this.advisorFactory.getAdvisors(factory));
   }
  }
  return advisors;
 }

3.3.2 findAdvisorsThatCanApply

描述:用所有advisor匹配当前class获取当前类有效的advisor列表。

protected List<Advisor> findAdvisorsThatCanApply(
   List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

  ProxyCreationContext.setCurrentProxiedBeanName(beanName);
  try {
   /**
    * 判断当前类是否在这些切面的pointCut中
    */
   return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
  }
  finally {
   ProxyCreationContext.setCurrentProxiedBeanName(null);
  }
 }

描述:找到有效的Advisor后匹配当前bean是否需要加强

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) {
    // already processed
    continue;
   }

   /**
    * 判断当前类、方法是否匹配PointCut,如果匹配,把有效切面存入eligibleAdvisors
    */
   if (canApply(candidate, clazz, hasIntroductions)) {
    eligibleAdvisors.add(candidate);
   }
  }
  return eligibleAdvisors;
 }


描述:真正匹配方法,判断当前类是否在pointCut表达式中,在匹配当前方法是否需要加强。

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
  Assert.notNull(pc, "Pointcut must not be null");

  /**
   * 【1】判断当前类是否匹配Pointcut
   */
  if (!pc.getClassFilter().matches(targetClass)) {
   return false;
  }

  MethodMatcher methodMatcher = pc.getMethodMatcher();
  if (methodMatcher == MethodMatcher.TRUE) {
   // No need to iterate the methods if we're matching any method anyway...
   return true;
  }

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

  /**
   * 【2】 判断类中方法是否匹配
   */
  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;
 }

4 buildAspectJAdvisors() 方法debug

描述:该方法是获取当前项目中所有advisor。一个advisor由pointCut和advice组成,代表一个切面。

public List<Advisor> buildAspectJAdvisors() {
  List<String> aspectNames = this.aspectBeanNames;

  if (aspectNames == null) {
   synchronized (this) {
    aspectNames = this.aspectBeanNames;
    if (aspectNames == null) {
     List<Advisor> advisors = new ArrayList<>();
     aspectNames = new ArrayList<>();

     /**
      * 从spring 中获取所有的类
      */
     String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
       this.beanFactory, Object.class, truefalse);
     for (String beanName : beanNames) {
      if (!isEligibleBean(beanName)) {
       continue;
      }
      // We must be careful not to instantiate beans eagerly as in this case they
      // would be cached by the Spring container but would not have been weaved.

      /**
       *  获取beanName 的class
       */
      Class<?> beanType = this.beanFactory.getType(beanName);
      if (beanType == null) {
       continue;
      }

      /**
       *  判断类上是否有@Aspect注解
       */
      if (this.advisorFactory.isAspect(beanType)) {
       aspectNames.add(beanName);
       AspectMetadata amd = new AspectMetadata(beanType, beanName);
       if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {

        //创建获取有@Aspect注解类的实例工厂,负责获取有@Aspect注解的实例
        MetadataAwareAspectInstanceFactory factory =
          new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);

        //创建切面Advisor对象
        List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
        if (this.beanFactory.isSingleton(beanName)) {
         this.advisorsCache.put(beanName, classAdvisors);
        }
        else {
         this.aspectFactoryCache.put(beanName, factory);
        }
        advisors.addAll(classAdvisors);
       }
       else {
        // Per target or per this.
        if (this.beanFactory.isSingleton(beanName)) {
         throw new IllegalArgumentException("Bean with name '" + beanName +
           "' is a singleton, but aspect instantiation model is not singleton");
        }
        MetadataAwareAspectInstanceFactory factory =
          new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
        this.aspectFactoryCache.put(beanName, factory);
        advisors.addAll(this.advisorFactory.getAdvisors(factory));
       }
      }
     }
     this.aspectBeanNames = aspectNames;
     return advisors;
    }
   }
  }

  if (aspectNames.isEmpty()) {
   return Collections.emptyList();
  }
  List<Advisor> advisors = new ArrayList<>();
  for (String aspectName : aspectNames) {
   List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
   if (cachedAdvisors != null) {
    advisors.addAll(cachedAdvisors);
   }
   else {
    MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
    advisors.addAll(this.advisorFactory.getAdvisors(factory));
   }
  }
  return advisors;
 }

描述:创建pointCut对象


描述:创建advisor对象,传入参数pointCut。advisor创建时,会创建内部advice对象。

描述:创建advice

5 匹配流程debug

描述:匹配类,切点进入当前类,在matches方法中,会把切点转成表达式。

描述:如果类、方法都匹配advisor,那么当前advisor可以加强当前bean

————————————————

版权声明:本文为CSDN博主「你携秋月揽星河丶」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:

https://blog.csdn.net/qq_34125999/article/details/115057552





粉丝福利:Java从入门到入土学习路线图

👇👇👇

👆长按上方微信二维码 2 秒


感谢点赞支持下哈 

浏览 37
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报