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

创建一个 Advice 对象,包含了对应的 Pointcut

private AbstractBeanDefinition createAdviceDefinition( Element adviceElement, ParserContext parserContext, String aspectName, int order, RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef, List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) { // <1> 根据 Advice 标签创建对应的 Advice // <aop:before /> -> AspectJMethodBeforeAdvice // <aop:after /> -> AspectJAfterAdvice // <aop:after-returning /> -> AspectJAfterReturningAdvice // <aop:after-throwing /> -> AspectJAfterThrowingAdvice // <aop:around /> -> AspectJAroundAdvice RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext)); // <1.1> 设置来源 adviceDefinition.setSource(parserContext.extractSource(adviceElement)); // <1.2> 设置引用的 AspectJ 的名称 adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName); // <1.3> 设置优先级 adviceDefinition.getPropertyValues().add(DECLARATION_ORDER_PROPERTY, order); if (adviceElement.hasAttribute(RETURNING)) { adviceDefinition.getPropertyValues().add( RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING)); } if (adviceElement.hasAttribute(THROWING)) { adviceDefinition.getPropertyValues().add( THROWING_PROPERTY, adviceElement.getAttribute(THROWING)); } if (adviceElement.hasAttribute(ARG_NAMES)) { adviceDefinition.getPropertyValues().add( ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES)); } // <2> 获取 Advice 的构造器参数对象 `cav` // 设置 1. 引用的方法、2. Pointcut(也许是引用的 Pointcut 的名称)、3. 引用的方法所属 AspectJ 对象 // 你点进这些 Advice 类型的对象中看看构造方法就知道怎么回事,例如:AspectJMethodBeforeAdvice ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues(); // <2.1> 往 `cav` 添加 Advice 对应的方法作为入参 cav.addIndexedArgumentValue(METHOD_INDEX, methodDef); // <2.2> 解析出对应的 Pointcut 对象(可能是一个 AspectJExpressionPointcut,也可能是引用的 Pointcut 的一个运行时引用对象) Object pointcut = parsePointcutProperty(adviceElement, parserContext); // <2.2.1> 如果是 AspectJExpressionPointcut if (pointcut instanceof BeanDefinition) { // 往 `cav` 添加 `pointcut` 入参 cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcut); // 添加至 `beanDefinitions` beanDefinitions.add((BeanDefinition) pointcut); } // <2.2.2> 否则,如果是 引用的 Pointcut else if (pointcut instanceof String) { // 根据引用的 Pointcut 的名称生成一个引用对象 RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String) pointcut); // 往构 `cav` 添加 `pointcut` 入参 cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef); // 添加至 `pointcutRef` beanReferences.add(pointcutRef); } // <2.3> 往 `cav` 添加 Advice 对应的方法所在 Bean 作为入参 cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef); // <3> 返回为 Advice 创建的 RootBeanDefinition 对象 return adviceDefinition; } private Class<?> getAdviceClass(Element adviceElement, ParserContext parserContext) { String elementName = parserContext.getDelegate().getLocalName(adviceElement); if (BEFORE.equals(elementName)) { return AspectJMethodBeforeAdvice.class; } else if (AFTER.equals(elementName)) { return AspectJAfterAdvice.class; } else if (AFTER_RETURNING_ELEMENT.equals(elementName)) { return AspectJAfterReturningAdvice.class; } else if (AFTER_THROWING_ELEMENT.equals(elementName)) { return AspectJAfterThrowingAdvice.class; } else if (AROUND.equals(elementName)) { return AspectJAroundAdvice.class; } else { throw new IllegalArgumentException("Unknown advice kind [" + elementName + "]."); } }

创建一个 AspectJPointcutAdvisor 类型的 RootBeanDefinition 对象,用于包装上面创建的 Advice,Spring AOP 中的 Advice 都是放入 Advisor “容器” 中

注册这个 AspectJPointcutAdvisor,自动生成名字

返回这个已注册的 AspectJPointcutAdvisor

------------------------------------ Spring Boot 注解驱动

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

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