• Spring Aop注解配置源码分析(1)


    1.概念    

    先了解下Spring Aop的几个概念

    Aspect:切面,我们用注解配置aop的话就是加了@Aspect注解的类

    Join point:连接点:程序执行过程中的一个点,也就是被代理接口或类的方法的执行

    Advice:增强,通过@Before,@Around注解定义的方法,Spring会在连接点建立一个拦截器链,增强围绕着连接点进行的

    Pointcut:切点,也就是匹配连接点的表达式

    Introduction:不修改代理对象的代码,从而增加额外的行为

    Target :目标对象,也就是被代理的对象,可以通过连接点point.getTarget()来获取到对应的代理对象

    AOP Proxy:aop所使用的代理方式,jdk动态代理,cglib动态代理

    Weaving:织入,运行时在执行增强的代码

    通知类型:

    Before advice: 在连接点之前运行,不能阻止连接点的运行,除非抛出异常

    After returning advice: 在连接点正常完成后运行的通知,连接点方法没有抛出异常

    After throwing advice: 方法抛出异常会执行此通知

    After (finally) advice: 无论连接点以何种方式退出(正常或异常返回),都将运行通知

    Around advice: 围绕连接点的建议,例如方法调用。环绕通知可以在方法调用之前和之后执行自定义行为。它还负责选择是继续到连接点还是通过返回自己的返回值或抛出异常来缩短建议的方法执行

    Springboot Aop自动装配博客地址:SpringBoot Aop自动装配源码解析_LouD_dm的博客-CSDN博客

    Springboo中默认使用注解的aop配置,自动装配的类是:AnnotationAwareAspectJAutoProxyCreator

    2.AnnotationAwareAspectJAutoProxyCreator继承图

    AnnotationAwareAspectJAutoProxyCreator:springboot默认自动装配的类,处理加了@Aspect注解的类

    AspectJAwareAdvisorAutoProxyCreator:暴露 AspectJ 的调用上下文并理解 AspectJ 规则的子类

    AbstractAdvisorAutoProxyCreator:为特定 bean 构建 AOP 代理的通用自动代理创建器

    AbstractAutoProxyCreator:BeanPostProcessor实现,使用 AOP 代理包装每个符合条件的 bean,委托给指定的拦截器

    ProxyProcessorSupport:具有代理处理器通用功能的基类,特别是ClassLoader 管理和 {link #evaluateProxyInterfaces} 算法。

    ProxyConfig:用于创建代理的配置的便利超类, 确保所有代理创建者具有一致的属性。

    AopInfrastructureBean:实现此接口的类不被代理

    SmartInstantiationAwareBeanPostProcessor:用于预测已处理Bean最终类型的回调

    InstantiationAwareBeanPostProcessor:实现了BeanPostProcessor接口,增加Bean初始化前后的回调

    BeanPostProcessor:Bean后置处理器,Spring初始化Bean时会调用注册的Bean后置处理器

    3.涉及到的其他接口和类

    Advice增强

    Advisor建议(一个切面可以包含多个建议,多个建议里包含通知,切点)

    4.初始化流程

    首先看核心类 AbstractAutoProxyCreator,这个类实现了SmartInstantiationAwareBeanPostProcessor接口,意味着Spring中bean的初始化前后会调用SmartInstantiationAwareBeanPostProcessor后置处理器的方法

    AbstractAutoProxyCreator重写了postProcessBeforeInstantiation,getEarlyBeanReference方法

    postProcessBeforeInstantiation和postProcessAfterInstantiation在bean初始化前还没有调用填充属性之前执行

    getEarlyBeanReference在bean填充属性之前,初始化调用postProcessBeforeInstantiation之后

    1)首先看postProcessBeforeInstantiation方法,如果自定义TargetSource可以提前生成代理,

    这里getAdvicesAndAdvisorsForBean收集所有的Advisor(建议),之后调用createProxy创建bean的代理

    1. @Override
    2. public Object postProcessBeforeInstantiation(Class beanClass, String beanName) {
    3. Object cacheKey = getCacheKey(beanClass, beanName);
    4. if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
    5. if (this.advisedBeans.containsKey(cacheKey)) {
    6. return null;
    7. }
    8. if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
    9. this.advisedBeans.put(cacheKey, Boolean.FALSE);
    10. return null;
    11. }
    12. }
    13. // 如果我们有自定义 TargetSource,请在此处创建代理。
    14. // 抑制目标 bean 的不必要的默认实例化:
    15. // TargetSource 将以自定义方式处理目标实例。
    16. TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
    17. if (targetSource != null) {
    18. if (StringUtils.hasLength(beanName)) {
    19. this.targetSourcedBeans.add(beanName);
    20. }
    21. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
    22. Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
    23. this.proxyTypes.put(cacheKey, proxy.getClass());
    24. return proxy;
    25. }
    26. return null;
    27. }

     getEarlyBeanReference方法同样也是收集Advisor,创建代理,只不过一个是自定义targetSource,一个是使用的SingletonTargetSource

    1. @Override
    2. public Object getEarlyBeanReference(Object bean, String beanName) {
    3. Object cacheKey = getCacheKey(bean.getClass(), beanName);
    4. this.earlyProxyReferences.put(cacheKey, bean);
    5. return wrapIfNecessary(bean, beanName, cacheKey);
    6. }
    7. /**
    8. * 如有必要,包装给定的 bean,即如果它有资格被代理。
    9. *
    10. * @param bean the raw bean instance
    11. * @param beanName the name of the bean
    12. * @param cacheKey the cache key for metadata access
    13. * @return a proxy wrapping the bean, or the raw bean instance as-is
    14. */
    15. protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    16. if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
    17. return bean;
    18. }
    19. if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
    20. return bean;
    21. }
    22. if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
    23. this.advisedBeans.put(cacheKey, Boolean.FALSE);
    24. return bean;
    25. }
    26. // 如果我们有建议,请创建代理.
    27. // 获取bean所有的Advisor
    28. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    29. if (specificInterceptors != DO_NOT_PROXY) {
    30. this.advisedBeans.put(cacheKey, Boolean.TRUE);
    31. //创建对应的代理,使用SingletonTargetSource
    32. Object proxy = createProxy(
    33. bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
    34. this.proxyTypes.put(cacheKey, proxy.getClass());
    35. return proxy;
    36. }
    37. this.advisedBeans.put(cacheKey, Boolean.FALSE);
    38. return bean;
    39. }

     子类AbstractAdvisorAutoProxyCreator实现了getAdvicesAndAdvisorsForBean收集建议的方法

    1. @Override
    2. @Nullable
    3. protected Object[] getAdvicesAndAdvisorsForBean(
    4. Class beanClass, String beanName, @Nullable TargetSource targetSource) {
    5. List advisors = findEligibleAdvisors(beanClass, beanName);
    6. if (advisors.isEmpty()) {
    7. return DO_NOT_PROXY;
    8. }
    9. return advisors.toArray();
    10. }
    11. /**
    12. * 查找所有符合条件的顾问以自动代理此类。
    13. * @param beanClass the clazz to find advisors for
    14. * @param beanName the name of the currently proxied bean
    15. * @return the empty List, not {@code null},
    16. * if there are no pointcuts or interceptors
    17. * @see #findCandidateAdvisors
    18. * @see #sortAdvisors
    19. * @see #extendAdvisors
    20. */
    21. protected List findEligibleAdvisors(Class beanClass, String beanName) {
    22. //获取所有的Advisor
    23. List candidateAdvisors = findCandidateAdvisors();
    24. //根据当前bean做筛选
    25. List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    26. extendAdvisors(eligibleAdvisors);
    27. if (!eligibleAdvisors.isEmpty()) {
    28. eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    29. }
    30. return eligibleAdvisors;
    31. }

     findCandidateAdvisors方法调用的advisorRetrievalHelper来查找bean

    1. /**
    2. * 查找要在自动代理中使用的所有候选顾问。
    3. * @return the List of candidate Advisors
    4. */
    5. protected List findCandidateAdvisors() {
    6. Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
    7. return this.advisorRetrievalHelper.findAdvisorBeans();
    8. }

     advisorRetrievalHelper.findAdvisorBeans方法从spring中查找advisor类型的bean返回

    1. /**
    2. * 查找当前 bean factory 中所有符合条件的 Advisor bean,
    3. * 忽略 FactoryBeans 并排除当前正在创建的 bean。
    4. *
    5. * @return the list of {@link org.springframework.aop.Advisor} beans
    6. * @see #isEligibleBean
    7. */
    8. public List findAdvisorBeans() {
    9. // 确定顾问 bean 名称列表(如果尚未缓存)。
    10. String[] advisorNames = this.cachedAdvisorBeanNames;
    11. if (advisorNames == null) {
    12. // 不要在此处初始化 FactoryBeans:我们需要保留所有常规 bean
    13. // 未初始化以让自动代理创建者应用到它们!
    14. advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
    15. this.beanFactory, Advisor.class, true, false);
    16. this.cachedAdvisorBeanNames = advisorNames;
    17. }
    18. if (advisorNames.length == 0) {
    19. return new ArrayList<>();
    20. }
    21. List advisors = new ArrayList<>();
    22. for (String name : advisorNames) {
    23. if (isEligibleBean(name)) {
    24. if (this.beanFactory.isCurrentlyInCreation(name)) {
    25. if (logger.isTraceEnabled()) {
    26. logger.trace("Skipping currently created advisor '" + name + "'");
    27. }
    28. } else {
    29. try {
    30. advisors.add(this.beanFactory.getBean(name, Advisor.class));
    31. } catch (BeanCreationException ex) {
    32. Throwable rootCause = ex.getMostSpecificCause();
    33. if (rootCause instanceof BeanCurrentlyInCreationException) {
    34. BeanCreationException bce = (BeanCreationException) rootCause;
    35. String bceBeanName = bce.getBeanName();
    36. if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
    37. if (logger.isTraceEnabled()) {
    38. logger.trace("Skipping advisor '" + name +
    39. "' with dependency on currently created bean: " + ex.getMessage());
    40. }
    41. // Ignore: indicates a reference back to the bean we're trying to advise.
    42. // We want to find advisors other than the currently created bean itself.
    43. continue;
    44. }
    45. }
    46. throw ex;
    47. }
    48. }
    49. }
    50. }
    51. return advisors;
    52. }

    筛选对应的bean

    1. /**
    2. * 搜索给定的候选顾问以查找所有符合条件的顾问
    3. * 可以应用于指定的bean。
    4. *
    5. * @param candidateAdvisors the candidate Advisors
    6. * @param beanClass the target's bean class
    7. * @param beanName the target's bean name
    8. * @return the List of applicable Advisors
    9. * @see ProxyCreationContext#getCurrentProxiedBeanName()
    10. */
    11. protected List findAdvisorsThatCanApply(
    12. List candidateAdvisors, Class beanClass, String beanName) {
    13. ProxyCreationContext.setCurrentProxiedBeanName(beanName);
    14. try {
    15. return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    16. } finally {
    17. ProxyCreationContext.setCurrentProxiedBeanName(null);
    18. }
    19. }

    筛选出类型是IntroductionAdvisor,并且适配当前bean的Advisor

    1. /**
    2. * 确定 {code CandidateAdvisors} 列表的子列表
    3. * 适用于给定类。
    4. *
    5. * @param candidateAdvisors the Advisors to evaluate
    6. * @param clazz the target class
    7. * @return sublist of Advisors that can apply to an object of the given class
    8. * (may be the incoming List as-is)
    9. */
    10. public static List findAdvisorsThatCanApply(List candidateAdvisors, Class clazz) {
    11. if (candidateAdvisors.isEmpty()) {
    12. return candidateAdvisors;
    13. }
    14. List eligibleAdvisors = new ArrayList<>();
    15. for (Advisor candidate : candidateAdvisors) {
    16. if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
    17. eligibleAdvisors.add(candidate);
    18. }
    19. }
    20. boolean hasIntroductions = !eligibleAdvisors.isEmpty();
    21. for (Advisor candidate : candidateAdvisors) {
    22. if (candidate instanceof IntroductionAdvisor) {
    23. // already processed
    24. continue;
    25. }
    26. if (canApply(candidate, clazz, hasIntroductions)) {
    27. eligibleAdvisors.add(candidate);
    28. }
    29. }
    30. return eligibleAdvisors;
    31. }
    32. /**
    33. * 给定的顾问可以完全适用于给定的课程吗?
    34. * 这是一个重要的测试,因为它可以用来优化
    35. * 出一个班级的顾问。
    36. *
    37. * @param advisor the advisor to check
    38. * @param targetClass class we're testing
    39. * @return whether the pointcut can apply on any method
    40. */
    41. public static boolean canApply(Advisor advisor, Class targetClass) {
    42. return canApply(advisor, targetClass, false);
    43. }
    44. /**
    45. * 给定的顾问可以完全适用于给定的课程吗?
    46. *

      这是一个重要的测试,因为它可以用来优化一个类的顾问。

    47. * 此版本还考虑了介绍(对于 IntroductionAwareMethodMatchers)。
    48. *
    49. * @param advisor the advisor to check
    50. * @param targetClass class we're testing
    51. * @param hasIntroductions whether or not the advisor chain for this bean includes
    52. * any introductions
    53. * @return whether the pointcut can apply on any method
    54. */
    55. public static boolean canApply(Advisor advisor, Class targetClass, boolean hasIntroductions) {
    56. if (advisor instanceof IntroductionAdvisor) {
    57. return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
    58. } else if (advisor instanceof PointcutAdvisor) {
    59. PointcutAdvisor pca = (PointcutAdvisor) advisor;
    60. return canApply(pca.getPointcut(), targetClass, hasIntroductions);
    61. } else {
    62. // It doesn't have a pointcut so we assume it applies.
    63. return true;
    64. }
    65. }

     接着回到findCandidateAdvisors方法,上面的流程是找Advisor类型的bean

    1. @Override
    2. protected List findCandidateAdvisors() {
    3. // 添加根据超类规则找到的所有 Spring 顾问。
    4. List advisors = super.findCandidateAdvisors();
    5. // 为 bean 工厂中的所有 AspectJ 方面构建顾问。
    6. if (this.aspectJAdvisorsBuilder != null) {
    7. advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    8. }
    9. return advisors;
    10. }

    下一步aspectJAdvisorsBuilder不为空的话执行下面的方法,AbstractAutoProxyCreator实现了BeanFactoryAware,bean初始化会调用setBeanFactory接口,AbstractAdvisorAutoProxyCreator重写了setBeanFactory接口,并调用了initBeanFactory方法自定义初始化BeanFactory,这里面已经初始化了aspectJAdvisorsBuilder 这个属性

    1. @Override
    2. public void setBeanFactory(BeanFactory beanFactory) {
    3. super.setBeanFactory(beanFactory);
    4. if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
    5. throw new IllegalArgumentException(
    6. "AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
    7. }
    8. initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
    9. }
    10. @Override
    11. protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    12. super.initBeanFactory(beanFactory);
    13. if (this.aspectJAdvisorFactory == null) {
    14. this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
    15. }
    16. this.aspectJAdvisorsBuilder =
    17. new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
    18. }

    BeanFactoryAdvisorRetrievalHelperAdapter的buildAspectJAdvisors方法,从容器中找到所有的bean名称,根据bean的class上是否加了Aspect来判断是否是切面,一般使用的切面都是单例类型的,之后包装一下切面的bean,从切面里找对应的Advisor,

    1. public List buildAspectJAdvisors() {
    2. List aspectNames = this.aspectBeanNames;
    3. if (aspectNames == null) {
    4. synchronized (this) {
    5. aspectNames = this.aspectBeanNames;
    6. if (aspectNames == null) {
    7. List advisors = new ArrayList<>();
    8. aspectNames = new ArrayList<>();
    9. String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
    10. this.beanFactory, Object.class, true, false);
    11. for (String beanName : beanNames) {
    12. if (!isEligibleBean(beanName)) {
    13. continue;
    14. }
    15. // 我们必须小心不要急切地实例化 bean,因为在这种情况下它们
    16. // 将被 Spring 容器缓存但不会被编织。
    17. Class beanType = this.beanFactory.getType(beanName);
    18. if (beanType == null) {
    19. continue;
    20. }
    21. if (this.advisorFactory.isAspect(beanType)) {
    22. aspectNames.add(beanName);
    23. AspectMetadata amd = new AspectMetadata(beanType, beanName);
    24. if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
    25. MetadataAwareAspectInstanceFactory factory =
    26. new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
    27. List classAdvisors = this.advisorFactory.getAdvisors(factory);
    28. if (this.beanFactory.isSingleton(beanName)) {
    29. this.advisorsCache.put(beanName, classAdvisors);
    30. } else {
    31. this.aspectFactoryCache.put(beanName, factory);
    32. }
    33. advisors.addAll(classAdvisors);
    34. } else {
    35. // Per target or per this.
    36. if (this.beanFactory.isSingleton(beanName)) {
    37. throw new IllegalArgumentException("Bean with name '" + beanName +
    38. "' is a singleton, but aspect instantiation model is not singleton");
    39. }
    40. MetadataAwareAspectInstanceFactory factory =
    41. new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
    42. this.aspectFactoryCache.put(beanName, factory);
    43. advisors.addAll(this.advisorFactory.getAdvisors(factory));
    44. }
    45. }
    46. }
    47. this.aspectBeanNames = aspectNames;
    48. return advisors;
    49. }
    50. }
    51. }
    52. if (aspectNames.isEmpty()) {
    53. return Collections.emptyList();
    54. }
    55. List advisors = new ArrayList<>();
    56. for (String aspectName : aspectNames) {
    57. List cachedAdvisors = this.advisorsCache.get(aspectName);
    58. if (cachedAdvisors != null) {
    59. advisors.addAll(cachedAdvisors);
    60. } else {
    61. MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
    62. advisors.addAll(this.advisorFactory.getAdvisors(factory));
    63. }
    64. }
    65. return advisors;
    66. }

    判断是否是切面

    1. /**
    2. * 我们认为某些东西是适合 Spring AOP 系统使用的 AspectJ 方面
    3. * 如果它有 Aspect 注释,并且不是由 ajc 编译的。后一个测试的原因
    4. * 是以代码风格(AspectJ 语言)编写的方面也存在注释
    5. * 当带有 -1.5 标志的 ajc 编译时,它们不能被 Spring AOP 使用。
    6. */
    7. @Override
    8. public boolean isAspect(Class clazz) {
    9. return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
    10. }
    11. private boolean hasAspectAnnotation(Class clazz) {
    12. return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
    13. }
    14. /**
    15. * 我们需要将其检测为“代码风格”的 AspectJ 方面不应该
    16. * 由 Spring AOP 解释。
    17. */
    18. private boolean compiledByAjc(Class clazz) {
    19. // AJTypeSystem 竭尽全力在代码风格和
    20. // 注释样式方面。因此,没有“干净”的方法可以区分它们。在这里我们依靠
    21. // AspectJ 编译器的实现细节。
    22. for (Field field : clazz.getDeclaredFields()) {
    23. if (field.getName().startsWith(AJC_MAGIC)) {
    24. return true;
    25. }
    26. }
    27. return false;
    28. }

    根据bean查找Advisor,找对应class下面所有没有Pointcut注解的方法,之后根据方法找到对应

    1. @Override
    2. public List getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
    3. Class aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    4. String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
    5. validate(aspectClass);
    6. // 我们需要用装饰器包装 MetadataAwareAspectInstanceFactory
    7. // 这样它只会实例化一次。
    8. MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
    9. new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
    10. List advisors = new ArrayList<>();
    11. for (Method method : getAdvisorMethods(aspectClass)) {
    12. Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
    13. if (advisor != null) {
    14. advisors.add(advisor);
    15. }
    16. }
    17. //懒加载处理
    18. if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
    19. Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
    20. advisors.add(0, instantiationAdvisor);
    21. }
    22. // 查找介绍字段.
    23. for (Field field : aspectClass.getDeclaredFields()) {
    24. Advisor advisor = getDeclareParentsAdvisor(field);
    25. if (advisor != null) {
    26. advisors.add(advisor);
    27. }
    28. }
    29. return advisors;
    30. }

    获取没有加Pointcut的方法,从方法里获取Advisor,也就是加了Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class注解的方法,封装为InstantiationModelAwarePointcutAdvisorImpl

    1. private List getAdvisorMethods(Class aspectClass) {
    2. final List methods = new ArrayList<>();
    3. ReflectionUtils.doWithMethods(aspectClass, method -> {
    4. // Exclude pointcuts
    5. if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
    6. methods.add(method);
    7. }
    8. }, ReflectionUtils.USER_DECLARED_METHODS);
    9. methods.sort(METHOD_COMPARATOR);
    10. return methods;
    11. }
    12. @Override
    13. @Nullable
    14. public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
    15. int declarationOrderInAspect, String aspectName) {
    16. validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
    17. AspectJExpressionPointcut expressionPointcut = getPointcut(
    18. candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
    19. if (expressionPointcut == null) {
    20. return null;
    21. }
    22. return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
    23. this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
    24. }
    25. @Nullable
    26. private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class candidateAspectClass) {
    27. AspectJAnnotation aspectJAnnotation =
    28. AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    29. if (aspectJAnnotation == null) {
    30. return null;
    31. }
    32. AspectJExpressionPointcut ajexp =
    33. new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class[0]);
    34. ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
    35. if (this.beanFactory != null) {
    36. ajexp.setBeanFactory(this.beanFactory);
    37. }
    38. return ajexp;
    39. }
    1. private static final Class[] ASPECTJ_ANNOTATION_CLASSES = new Class[]{
    2. Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
    3. @Nullable
    4. protected static AspectJAnnotation findAspectJAnnotationOnMethod(Method method) {
    5. for (Class clazz : ASPECTJ_ANNOTATION_CLASSES) {
    6. AspectJAnnotation foundAnnotation = findAnnotation(method, (Class) clazz);
    7. if (foundAnnotation != null) {
    8. return foundAnnotation;
    9. }
    10. }
    11. return null;
    12. }

    创建InstantiationModelAwarePointcutAdvisorImpl的构造方法,如果是单例找对应的通知,主要方法instantiateAdvice

    1. public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
    2. Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
    3. MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
    4. this.declaredPointcut = declaredPointcut;
    5. this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
    6. this.methodName = aspectJAdviceMethod.getName();
    7. this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
    8. this.aspectJAdviceMethod = aspectJAdviceMethod;
    9. this.aspectJAdvisorFactory = aspectJAdvisorFactory;
    10. this.aspectInstanceFactory = aspectInstanceFactory;
    11. this.declarationOrder = declarationOrder;
    12. this.aspectName = aspectName;
    13. if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
    14. // 切入点的静态部分是惰性类型。
    15. Pointcut preInstantiationPointcut = Pointcuts.union(
    16. aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
    17. //使其动态化:必须从实例化前状态转变为实例化后状态。
    18. // 如果不是动态切入点,可能会被优化掉
    19. // 在第一次评估之后由 Spring AOP 基础设施。
    20. this.pointcut = new PerTargetInstantiationModelPointcut(
    21. this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
    22. this.lazy = true;
    23. }
    24. else {
    25. // A singleton aspect.
    26. this.pointcut = this.declaredPointcut;
    27. this.lazy = false;
    28. this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
    29. }
    30. }

     从Advisor找对应的Advice,根据注解不同创建不同的Advice实现

    1. private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
    2. Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
    3. this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
    4. return (advice != null ? advice : EMPTY_ADVICE);
    5. }
    6. @Override
    7. @Nullable
    8. public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
    9. MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
    10. Class candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    11. validate(candidateAspectClass);
    12. AspectJAnnotation aspectJAnnotation =
    13. AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    14. if (aspectJAnnotation == null) {
    15. return null;
    16. }
    17. //如果我们到达这里,我们知道我们有一个 AspectJ 方法。
    18. // 检查它是否是一个 AspectJ 注释的类
    19. if (!isAspect(candidateAspectClass)) {
    20. throw new AopConfigException("Advice must be declared inside an aspect type: " +
    21. "Offending method '" + candidateAdviceMethod + "' in class [" +
    22. candidateAspectClass.getName() + "]");
    23. }
    24. if (logger.isDebugEnabled()) {
    25. logger.debug("Found AspectJ method: " + candidateAdviceMethod);
    26. }
    27. AbstractAspectJAdvice springAdvice;
    28. switch (aspectJAnnotation.getAnnotationType()) {
    29. case AtPointcut:
    30. if (logger.isDebugEnabled()) {
    31. logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
    32. }
    33. return null;
    34. case AtAround:
    35. springAdvice = new AspectJAroundAdvice(
    36. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
    37. break;
    38. case AtBefore:
    39. springAdvice = new AspectJMethodBeforeAdvice(
    40. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
    41. break;
    42. case AtAfter:
    43. springAdvice = new AspectJAfterAdvice(
    44. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
    45. break;
    46. case AtAfterReturning:
    47. springAdvice = new AspectJAfterReturningAdvice(
    48. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
    49. AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
    50. if (StringUtils.hasText(afterReturningAnnotation.returning())) {
    51. springAdvice.setReturningName(afterReturningAnnotation.returning());
    52. }
    53. break;
    54. case AtAfterThrowing:
    55. springAdvice = new AspectJAfterThrowingAdvice(
    56. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
    57. AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
    58. if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
    59. springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
    60. }
    61. break;
    62. default:
    63. throw new UnsupportedOperationException(
    64. "Unsupported advice type on method: " + candidateAdviceMethod);
    65. }
    66. // 现在配置建议...
    67. springAdvice.setAspectName(aspectName);
    68. springAdvice.setDeclarationOrder(declarationOrder);
    69. String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
    70. if (argNames != null) {
    71. springAdvice.setArgumentNamesFromStringArray(argNames);
    72. }
    73. springAdvice.calculateArgumentBindings();
    74. return springAdvice;
    75. }

    总结

    我们常用的注解实现的Aop,就是spring在bean初始化时看bean的class上是否加了切面的注解,如果加了,会找切面下的Advisor,每一个加了Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class注解的方法和切点会被封装为一个Advisor,Advisor里有对应的通知,spring会根据注解的不同创建不同的通知。

    有些地方还没看懂,之后在慢慢了解,之后就是Spring怎么根据Advisor创建对应bean的代理

  • 相关阅读:
    TFN MIX5 500 手持式光谱仪 合金分析仪 便携式X荧光光谱仪 合金手持式光谱仪
    【数据结构】模拟实现栈和队列
    基于 json-server 工具,模拟实现后端接口服务环境
    [附源码]SSM计算机毕业设计学生宿舍管理系统设计JAVA
    动物大全和动物识别系统毕业设计,动物大全和动物AI识别系统设计与实现,动物识别系统论文毕设作品参考
    Java使用动态规划算法思想解决01背包问题
    中国这么多 Java 开发者,应该诞生出生态级应用开发框架
    DQL命令查询数据(一)
    8.稳定性专题
    【笔记】打卡01 | 初学入门
  • 原文地址:https://blog.csdn.net/qq_39482039/article/details/125988220