死磕Spring之AOP篇 - Spring AOP注解驱动与XML配置 (8)

上面第 4.3 会解析相关 Advice 标签,我们一起来看看

<aop:aspect /> 的 Advice 子标签 private AbstractBeanDefinition parseAdvice( String aspectName, int order, Element aspectElement, Element adviceElement, ParserContext parserContext, List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) { try { this.parseState.push(new AdviceEntry(parserContext.getDelegate().getLocalName(adviceElement))); // create the method factory bean // <1> 创建 MethodLocatingFactoryBean 类型的 RootBeanDefinition // 因为通过标签配置的 Advice 对应的方法在其他 Bean 中,那么可以借助于 FactoryBean 来进行创建 RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class); // <1.1> 获取 `targetBeanName` 和 `method` 并进行设置 methodDefinition.getPropertyValues().add("targetBeanName", aspectName); methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method")); // <1.2> 设置这个 Bean 是由 Spring 内部合成的 methodDefinition.setSynthetic(true); // create instance factory definition // <2> 创建一个 SimpleBeanFactoryAwareAspectInstanceFactory 类型的 RootBeanDefinition RootBeanDefinition aspectFactoryDef = new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class); // <2.1> 设置了 AspectJ 对应的 名称,用于获取这个 AspectJ 的实例对象 aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName); // <2.2> 设置这个 Bean 是由 Spring 内部合成的 aspectFactoryDef.setSynthetic(true); // register the pointcut // <3> 创建一个 Advice 对象,包含了对应的 Pointcut AbstractBeanDefinition adviceDef = createAdviceDefinition( adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef, beanDefinitions, beanReferences); // configure the advisor // <4> 创建一个 AspectJPointcutAdvisor 类型的 RootBeanDefinition 对象,用于包装上面创建的 Advice // Spring AOP 中的 Advice 都是放入 Advisor “容器” 中 RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class); // <4.1> 设置来源 advisorDefinition.setSource(parserContext.extractSource(adviceElement)); // <4.2> 将上面创建的 Advice 对象作为构造器入参 advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef); // <4.3> 设置 `order` 优先级 if (aspectElement.hasAttribute(ORDER_PROPERTY)) { advisorDefinition.getPropertyValues().add( ORDER_PROPERTY, aspectElement.getAttribute(ORDER_PROPERTY)); } // register the final advisor // <5> 注册这个 AspectJPointcutAdvisor,自动生成名字 parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition); // <6> 返回这个已注册的 AspectJPointcutAdvisor return advisorDefinition; } finally { this.parseState.pop(); } }

处理过程大致如下:

创建 MethodLocatingFactoryBean 类型的 RootBeanDefinition,因为通过标签配置的 Advice 对应的方法在其他 Bean 中,那么可以借助于 FactoryBean 来进行创建

获取 targetBeanName 和 method 并进行设置

设置这个 Bean 是由 Spring 内部合成的

创建一个 SimpleBeanFactoryAwareAspectInstanceFactory 类型的 RootBeanDefinition

设置了 AspectJ 对应的 名称,用于获取这个 AspectJ 的实例对象

设置这个 Bean 是由 Spring 内部合成的

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zygssw.html