Spring源码学习13

在分析Aop源码之前最好先回顾下Aop相关知识点:https://blog.csdn.net/qq_23536449/article/details/96868578和实现Aop三种方式:https://blog.csdn.net/qq_23536449/article/details/96899712,Aop之DeclareParents使用https://blog.csdn.net/qq_23536449/article/details/97008737

1.在https://blog.csdn.net/qq_23536449/article/details/95071632文中提到了对自定义标签元素是如何实现的,有兴趣可以回顾下。实现Aop的关键肯定少不了对标签元素的解析,我们直接找到AopNameSpaceHandler类

 2.ConfigBeanDefinitionParser.parse方法;

@Override
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		//创建CompositeComponentDefinition对象
		CompositeComponentDefinition compositeDef =
				new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
		parserContext.pushContainingComponent(compositeDef);
		//注册或配置一个auto-proxy creator的beanDefinition
		configureAutoProxyCreator(parserContext, element);
		//获取aop:config元素的子element
		List<Element> childElts = DomUtils.getChildElements(element);
		for (Element elt: childElts) {
			String localName = parserContext.getDelegate().getLocalName(elt);
			//解析pointcut
			if (POINTCUT.equals(localName)) {
				parsePointcut(elt, parserContext);
			}
			//解析advisor
			else if (ADVISOR.equals(localName)) {
				parseAdvisor(elt, parserContext);
			}
			//解析aspect元素
			else if (ASPECT.equals(localName)) {
				parseAspect(elt, parserContext);
			}
		}

		parserContext.popAndRegisterContainingComponent();
		return null;
	}

主要做了两件事情

  • a.注册或者配置一个auto-proxy creator的bean definition
  • b.解析标签元素aop:point aop:advisor aop:aspect

2.先来先来关注下configureAutoProxyCreator(parserContext, element);

/**
	 * 配置支持'{@code <aop:config/>}'标签的auto-proxy creator的beanDefinition
	 * @see AopNamespaceUtils
	 */
	private void configureAutoProxyCreator(ParserContext parserContext, Element element) {
		AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);
	}

根据名称不难理解其实这里是根据需要注册AspectJAutoProxyCreator beanDefinition;然后我想说的是其实解析aspect-autoproxy标签的 AspectJAutoProxyBeanDefinitionParser也是做了同样的事情,不过他注册的是更NB的AnnotationAwareAspectJAutoProxyCreator.class,在AspectJAutoProxyCreator上扩展了对@AspectJ注解实现AOP的支持。所以下文我们分析auto-proxy creator时分析更NB的AnnotationAwareAspectJAutoProxyCreator.java。

public static void registerAspectJAutoProxyCreatorIfNecessary(
			ParserContext parserContext, Element sourceElement) {
		//注册AspectJAwareAdvisorAutoProxyCreator.class的beanDefinition
		BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary(
				parserContext.getRegistry(), parserContext.extractSource(sourceElement));
		//配置的proxy-target-class属性和expose-proxy属性的读取
		useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
		//注册一个组件bean到parserContext的CompositeComponentDefinition中
		registerComponentIfNecessary(beanDefinition, parserContext);
	}

private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) {
		if (sourceElement != null) {
			//获取proxy-target-class属性
			//如果proxy-target-class 属性值被设置为true,那么基于类的代理将起作用(这时需要cglib库)。
			// 如果proxy-target-class属值被设置为false或者这个属性被省略,那么标准的JDK 基于接口的代理将起作用
			//但是,即使设置为false,如果目标类没有生命接口,
			boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
			if (proxyTargetClass) {
				//获取到auto-proxy creator对应的BeanDefinition
				//并且设置proxy-target-class属性值
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			//获取expose-proxy属性
			//exposeProxy用来标记是否允许将代理对象以ThreadLocal的形式暴露给aop框架,以便通过AopContext对代理对象进行重复利用
			boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
			if (exposeProxy) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}
private static void registerComponentIfNecessary(BeanDefinition beanDefinition, ParserContext parserContext) {
		if (beanDefinition != null) {
			parserContext.registerComponent(
					new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME));
		}
	}

 这里是使用aop:config帮我们注册的auto-proxy creator的代码

public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
		return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
	}

当我们使用aop:aspect-autoproxy时注册的auto-proxy creator是这样子的

/**
	 * 如果有必要的话注册AspectJAnnotationAutoProxyCreator
	 * @param registry
	 * @param source
	 * @return
	 */
	public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
		//注册或者升级AspectJAnnotationAutoProxyCreator
		return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
	}

然后下面就是看看用户有没有配置了auto-proxy creator,并且根据优先级选择最NB的创建他的BeanDefinition注册到beanDefinitionRegistry;用于帮我们后面创建代理。

private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		//包含org.springframework.aop.config.internalAutoProxyCreator,可能是自己配置的
		//这时候我们需要根据优先级确定要使用的auto-proxy creator
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			//获取internalAutoProxyCreator的beandefinition
			BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			//判断和传递过来的bean的className不一致
			if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
				// beanDefinition中定义的internalAutoProxyCreator的优先级
				int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
				// 我们所需要的auto-proxy creator的优先级
				int requiredPriority = findPriorityForClass(cls);
				// 如果我们需求的auto-proxy creator的优先级高,则使用我们需要的
				if (currentPriority < requiredPriority) {
					apcDefinition.setBeanClassName(cls.getName());
				}
			}
			//如果已经存在了并且与将要创建的一样直接返回
			return null;
		}
		//创建auto-proxy creator的beanDefinition
		RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
		beanDefinition.setSource(source);
		//在普通属性中添加order属性 order 并且值代表最高优先级
		beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
		//设置bean的角色为内部
		beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		//注册beandefinition
		registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
		return beanDefinition;
	}

3.解析aop:pointcut;解析切入点beanDefinition然后注册到beanDefinitionRegistry

 首先我们来看下Spring中对pointcut的抽象

  •  Pointcut:Spring的核心pointcut抽象类;一个切点是一个{@link ClassFilter}和一个{@link MethodMatcher}的组合
  • ExpressionPointcut:由使用String表达式的pointcut实现的接口,扩展了expression的支持
  • AbstractExpressionPointcut:表达式pointcut的抽象超类,提供location和expression属性
  • ClassFilter:从给出的一系列目标目标classes过滤出符合的pointcut或者introduction;方法有matches(Class<?> clzz)切入点是否应用于给定的接口或目标类
  • MethodMatcher:{@link Pointcut}的一部分:检查目标方法是否符合advice的条件
  • IntroductionAwareMethodMatcher:一种特殊类型的{@link MethodMatcher},在匹配方法时会考虑intructions例如,如果没有introductions在目标类上,方法匹配器可能能够更有效地优化匹配
  • AspectJExpressionPointcut: Spring {@link org.springframework.aop.Pointcut}实现使用AspectJ编织器来评估切入点表达式,切入点表达式值是AspectJ表达式。 这个可以引用其他切入点并使用合成和其他操作

解析过程

/**
	 * 解析类似<aop:pointcut expression="execution(* *.aspectTest(..))" id="p1"/>
	 * 并注册BeanDefinition到BeanDefinitionRegistry
	 *
	 */
	private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) {
		//id属性
		String id = pointcutElement.getAttribute(ID);
		//expression属性
		String expression = pointcutElement.getAttribute(EXPRESSION);

		AbstractBeanDefinition pointcutDefinition = null;

		try {
			this.parseState.push(new PointcutEntry(id));
			//创建AspectJExpressionPointcut.class的beanDefinition
			pointcutDefinition = createPointcutDefinition(expression);
			pointcutDefinition.setSource(parserContext.extractSource(pointcutElement));
			//切点bean名称赋值为id
			String pointcutBeanName = id;
			if (StringUtils.hasText(pointcutBeanName)) {
				parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition);
			}
			else {
				//没有bean名称生成一个注册到beanDefinitonRegistry
				pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition);
			}
			//注册PointcutComponentDefinition到readerContext的containingComponent并通知监听器
			parserContext.registerComponent(
					new PointcutComponentDefinition(pointcutBeanName, pointcutDefinition, expression));
		}
		finally {
			this.parseState.pop();
		}

		return pointcutDefinition;
	}


/**
	 * 使用给定的pointcut表达式创建一个{@link AspectJExpressionPointcut}的beanDefinition
	 *
	 */
	protected AbstractBeanDefinition createPointcutDefinition(String expression) {
		RootBeanDefinition beanDefinition = new RootBeanDefinition(AspectJExpressionPointcut.class);
		beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
		beanDefinition.setSynthetic(true);
		beanDefinition.getPropertyValues().add(EXPRESSION, expression);
		return beanDefinition;
	}

4.解析aop:advisor标签;一个advisor元素中的配置可能对应多个增强比如MethodBeforeAdvice,AfterAdvcice,AfterReturnningAdvice

Spring对它的抽象

  • Advisor:持有AOP advice(增强,在连接点要执行的动作可以理解为补充逻辑)以及确定advice适用性的过滤器(例如切入点)的基本接口, <i>此接口不供Spring用户使用,但允许支持不同类型的advices。springAOP是符合AOP Alliance拦截api规范的,并且通过方法拦截, 这个接口支持不同使用interception类型的advice(增强),比如<b>before</b> and <b>after</b>
  • PointcutAdvisor:由pointcut驱动的所有Advisors的超级接口。方法getPointcut()返回当前advisor驱动的pointcut
  • AbstractPointcutAdvisor:{@link org.springframework.aop.PointcutAdvisor}实现的抽象基类。 可以为子类返回特定的pointcut/advisor或可自由配置的pointcut/advisor
  • AbstractBeanFactoryPointcutAdvisor:基于BeanFactory的抽象PointcutAdvisor, 允许将任何advice配置为对BeanFactory中的Advice bean的引用,如果在BeanFactory中运行)在初始化时增加松散耦合指定advice的beanName而不是advice自身对象为了在切入点实际匹配之前不初始化通知对象
  • DefaultBeanFactoryPointcutAdvisor:允许将任何增强配置为对BeanFactory中的Advice bean的引用并且基于BeaFactory具体的PointcutAdvisor, 通过使用beanFactory配置pointCut属性。

解析过程

/**
	 * 解析类似<aop:advisor advice-ref="explictAdvisor" pointcut-ref="p1" id="ea"/>
	 * 并使用提供的{@link BeanDefinitionRegistry}注册生成的{@link org.springframework.aop.Advisor}
	 * 和任何生成的{@link org.springframework.aop.Pointcut}。
	 *
	 */
	private void parseAdvisor(Element advisorElement, ParserContext parserContext) {
		AbstractBeanDefinition advisorDef = createAdvisorBeanDefinition(advisorElement, parserContext);
		//解析id属性
		String id = advisorElement.getAttribute(ID);

		try {
			this.parseState.push(new AdvisorEntry(id));
			//advisorBeanName 赋值
			String advisorBeanName = id;
			if (StringUtils.hasText(advisorBeanName)) {
				parserContext.getRegistry().registerBeanDefinition(advisorBeanName, advisorDef);
			}
			//为advisorbean生成一个名称并注册bean
			else {
				advisorBeanName = parserContext.getReaderContext().registerWithGeneratedName(advisorDef);
			}
			//解析advisor标签元素的pointcut属性
			Object pointcut = parsePointcutProperty(advisorElement, parserContext);
			if (pointcut instanceof BeanDefinition) {
				advisorDef.getPropertyValues().add(POINTCUT, pointcut);
				//注册AdvisorComponentDefinition到readerContext的containingComponent并通知监听器
				parserContext.registerComponent(
						new AdvisorComponentDefinition(advisorBeanName, advisorDef, (BeanDefinition) pointcut));
			}
			else if (pointcut instanceof String) {
				//注册AdvisorComponentDefinition到readerContext的containingComponent并通知监听器
				advisorDef.getPropertyValues().add(POINTCUT, new RuntimeBeanReference((String) pointcut));
				parserContext.registerComponent(
						new AdvisorComponentDefinition(advisorBeanName, advisorDef));
			}
		}
		finally {
			this.parseState.pop();
		}
	}
/**
	 * 为给定的advisor的xml描述创建一个{@link RootBeanDefinition},不解析'{@code pointcut}' or '{@code pointcut-ref}'
	 */
	private AbstractBeanDefinition createAdvisorBeanDefinition(Element advisorElement, ParserContext parserContext) {
		//创建DefaultBeanFactoryPointcutAdvisor.class的bean definition
		RootBeanDefinition advisorDefinition = new RootBeanDefinition(DefaultBeanFactoryPointcutAdvisor.class);
		advisorDefinition.setSource(parserContext.extractSource(advisorElement));
		//advice-ref属性
		String adviceRef = advisorElement.getAttribute(ADVICE_REF);
		//没有指定增强类 报错
		if (!StringUtils.hasText(adviceRef)) {
			parserContext.getReaderContext().error(
					"'advice-ref' attribute contains empty value.", advisorElement, this.parseState.snapshot());
		}
		else {
			//添加adviceBeanName属性,类型为RuntimeBeanNameReference
			advisorDefinition.getPropertyValues().add(
					ADVICE_BEAN_NAME, new RuntimeBeanNameReference(adviceRef));
		}
		//如果有order属性,添加到beanDefinition
		if (advisorElement.hasAttribute(ORDER_PROPERTY)) {
			advisorDefinition.getPropertyValues().add(
					ORDER_PROPERTY, advisorElement.getAttribute(ORDER_PROPERTY));
		}

		return advisorDefinition;
	}


/**
	 *
	 * 解析所提供的{@link Element}的{@code pointcut}或{@code pointcut-ref}属性,并根据需要添加{@code pointcut}属性
	 * 如有必要,为切入点生成{@link org.springframework.beans.factory.config.BeanDefinition}并返回其bean名称,
	 * 否则返回引用切入点的bean名称
	 */
	private Object parsePointcutProperty(Element element, ParserContext parserContext) {
		//pointcut 和pointcut-ref属性都有 报错
		if (element.hasAttribute(POINTCUT) && element.hasAttribute(POINTCUT_REF)) {
			parserContext.getReaderContext().error(
					"Cannot define both 'pointcut' and 'pointcut-ref' on <advisor> tag.",
					element, this.parseState.snapshot());
			return null;
		}
		//包含pointcut属性,
		else if (element.hasAttribute(POINTCUT)) {
			// 解析并创建AspectJExpressionPointcut类型的beanDefinition
			String expression = element.getAttribute(POINTCUT);
			AbstractBeanDefinition pointcutDefinition = createPointcutDefinition(expression);
			pointcutDefinition.setSource(parserContext.extractSource(element));
			return pointcutDefinition;
		}
		//包含的是pointcut-ref属性
		else if (element.hasAttribute(POINTCUT_REF)) {
			String pointcutRef = element.getAttribute(POINTCUT_REF);
			//属性值为空,抛出异常
			if (!StringUtils.hasText(pointcutRef)) {
				parserContext.getReaderContext().error(
						"'pointcut-ref' attribute contains empty value.", element, this.parseState.snapshot());
				return null;
			}
			return pointcutRef;
		}
		else {
			parserContext.getReaderContext().error(
					"Must define one of 'pointcut' or 'pointcut-ref' on <advisor> tag.",
					element, this.parseState.snapshot());
			return null;
		}
	}

不难理解advisor包含两部分,一部分是pointcut解析另外一部分就是advice的解析。

5.解析aop:aspect标签元素;aspect标签元素分为两部分解析aop:before,aop:after,aop:around等类似标签元素,还有一部分是aop:declare-parents关于他的用法我们在文章开头已经提到过了

 我们先看前半部分的解析即解析aop:declare-parents

关于declare-parents的抽象

IntroductionInfo:提供描述一个introduction必须信息的接口,他有一个方法即:getInterfaces()返回此Advisor或Advice引入的其他接口

IntroductionAdvisor:更多AOP行为的advisors的超类 ;接口不能直接实现; 子接口必须提供introduction的增强类型实现 ;给目标添加未实现接口的AOP增强

DeclareParentsAdvisor:委托给给定对象的Intruction的advisor,可以在AspectJ注解内部通过@DeclareParents实现增强行为

代码解析部分

private void parseAspect(Element aspectElement, ParserContext parserContext) {
		//解析Id
		String aspectId = aspectElement.getAttribute(ID);
		//解析ref
		String aspectName = aspectElement.getAttribute(REF);

		try {
			this.parseState.push(new AspectEntry(aspectId, aspectName));
			List<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>();
			List<BeanReference> beanReferences = new ArrayList<BeanReference>();
			//解析这种标签元素
			/**
			 * <aop:declare-parents implement-interface="org.springframework.study.day13.IDeclareParent"
			 * types-matching="org.springframework.study.day13.NoMethodAspectBean"
			 * default-impl="org.springframework.study.day13.IDeclareParentImpl"/>
			 */
			List<Element> declareParents = DomUtils.getChildElementsByTagName(aspectElement, DECLARE_PARENTS);
			for (int i = METHOD_INDEX; i < declareParents.size(); i++) {
				Element declareParentsElement = declareParents.get(i);
				beanDefinitions.add(parseDeclareParents(declareParentsElement, parserContext));
			}

/**
	 * 解析'{@code declare-parents}'元素并使用封装在提供的ParserContext中的BeanDefinitionRegistry
	 * 注册相应的DeclareParentsAdvisor。
	 */
	private AbstractBeanDefinition parseDeclareParents(Element declareParentsElement, ParserContext parserContext) {
		//使用BeanDefinition的建造器解析declare-parents元素
		BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(DeclareParentsAdvisor.class);
		//implement-interface属性
		builder.addConstructorArgValue(declareParentsElement.getAttribute(IMPLEMENT_INTERFACE));
		//types-matching属性
		builder.addConstructorArgValue(declareParentsElement.getAttribute(TYPE_PATTERN));
		//default-impl属性
		String defaultImpl = declareParentsElement.getAttribute(DEFAULT_IMPL);
		//delegate-ref属性
		String delegateRef = declareParentsElement.getAttribute(DELEGATE_REF);
		//default-impl属性和delegate-ref只需要配置一个
		if (StringUtils.hasText(defaultImpl) && !StringUtils.hasText(delegateRef)) {
			builder.addConstructorArgValue(defaultImpl);
		}
		else if (StringUtils.hasText(delegateRef) && !StringUtils.hasText(defaultImpl)) {
			builder.addConstructorArgReference(delegateRef);
		}
		else {
			parserContext.getReaderContext().error(
					"Exactly one of the " + DEFAULT_IMPL + " or " + DELEGATE_REF + " attributes must be specified",
					declareParentsElement, this.parseState.snapshot());
		}

		AbstractBeanDefinition definition = builder.getBeanDefinition();
		definition.setSource(parserContext.extractSource(declareParentsElement));
		//使用生成的beanName注册beanDefinition
		parserContext.getReaderContext().registerWithGeneratedName(definition);
		return definition;
	}

然后是解析advice元素;aop:before,aop:after,aop:around等类似标签元素,对于每个元素的增强,Spring将他们封装为AspectJPointcutAdvisor对象

AspectJPointcutAdvisor:适配{@link AbstractAspectJAdvice}到{@link org.springframework.aop.PointcutAdvisor} 接口的类,其属性包括切入点和AbstractAspectJadvice属性

/**
	 * 解析'{@code before}', '{@code after}', '{@code after-returning}',
	 * 	  '{@code after-throwing}' or '{@code around}'并且注册beanDefinition
	 * 	 到给定的BeanDefinitionRegistry
	 * @return the generated advice RootBeanDefinition
	 */
	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)));

			//创建一个MethodFactoryBean的definition
			RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class);
			//设置几个属性
			methodDefinition.getPropertyValues().add("targetBeanName", aspectName);
			methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method"));
			methodDefinition.setSynthetic(true);

			//这个beanDefinition用于生产aspectName对应的bean
			RootBeanDefinition aspectFactoryDef =
					new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);
			aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName);
			aspectFactoryDef.setSynthetic(true);

			// register the pointcut
			//注册pointcut
			AbstractBeanDefinition adviceDef = createAdviceDefinition(
					adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef,
					beanDefinitions, beanReferences);

			// configure the advisor
			// 创建AspectJPointcutAdvisor的定义并配置
			RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class);
			advisorDefinition.setSource(parserContext.extractSource(adviceElement));
			advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef);
			if (aspectElement.hasAttribute(ORDER_PROPERTY)) {
				advisorDefinition.getPropertyValues().add(
						ORDER_PROPERTY, aspectElement.getAttribute(ORDER_PROPERTY));
			}
			// 注册advisor定义
			parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);

			return advisorDefinition;
		}
		finally {
			this.parseState.pop();
		}
	}


	/**
	 * Creates the RootBeanDefinition for a POJO advice bean. Also causes pointcut
	 * parsing to occur so that the pointcut may be associate with the advice bean.
	 * This same pointcut is also configured as the pointcut for the enclosing
	 * Advisor definition using the supplied MutablePropertyValues.
	 *
	 * 为advice bean创建RootBeanDefinition。这会导致解析pointcut并且与advice bean相关联.
	 * 同样的切入点也被配置为使用提供的MutablePropertyValues封闭Advisor定义的pointcut
	 */
	private AbstractBeanDefinition createAdviceDefinition(
			Element adviceElement, ParserContext parserContext, String aspectName, int order,
			RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef,
			List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {
		//创建advice的beanDefinitoin
		RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext));
		adviceDefinition.setSource(parserContext.extractSource(adviceElement));
		//设置相关属性
		adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName);
		adviceDefinition.getPropertyValues().add(DECLARATION_ORDER_PROPERTY, order);
		//包含returning属性
		if (adviceElement.hasAttribute(RETURNING)) {
			adviceDefinition.getPropertyValues().add(
					RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING));
		}
		//包含throwing属性
		if (adviceElement.hasAttribute(THROWING)) {
			adviceDefinition.getPropertyValues().add(
					THROWING_PROPERTY, adviceElement.getAttribute(THROWING));
		}
		//arg-names属性
		if (adviceElement.hasAttribute(ARG_NAMES)) {
			adviceDefinition.getPropertyValues().add(
					ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES));
		}
		//各类Advice的构造函数赋值谢谢
		ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues();
		cav.addIndexedArgumentValue(METHOD_INDEX, methodDef);
		Object pointcut = parsePointcutProperty(adviceElement, parserContext);
		if (pointcut instanceof BeanDefinition) {
			cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcut);
			beanDefinitions.add((BeanDefinition) pointcut);
		}
		else if (pointcut instanceof String) {
			RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String) pointcut);
			cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef);
			beanReferences.add(pointcutRef);
		}

		cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef);

		return adviceDefinition;
	}

  • a.该增强是那个bean的某个方法实现的MethodLocatingFactoryBean.class的beanDefinition
  • b.该增强bean的工厂创建类SimpleBeanFactoryAwareAspectInstanceFactory
  • c.根据a、b两步骤创建advice标签元素aop:before,aop:after,aop:around等类似标签元素对应的advice的beanDefinition如AspectJMethodBeforeAdvice、AspectJAfterReturningAdvice、AspectJAfterAdvice的beanDefinition
  • d.将advice适配为AspectJPointcutAdvisor类型的beanDefinition

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值