Spring-AOP 的BeanDefinition准备工作

(目标:AOP 实例化advisors)

AOP所需要的基础对象,在实例化前需要提前创建,那么对应到IOC的流程中,应该通过BeanPostProcessor来处理。

首先来分析下BeanPostProcessor的接口与实现类的关系,分析它执行的流程:

BeanPostProcessor的接口方法:

postProcessBeforeInitialization
postProcessAfterInitialization

InstantiationAwareBeanPostProcessor的方法:
postProcessBeforeInstantiation
postProcessAfterInstantiation
postProcessProperties

IOC中的进行AOP的对应流程源码:

AbstractAutowireCapableBeanFactory#createBean

protected Object createBean(String beanName, RootBeanDefinition mbd){
    ...
    // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    if (bean != null) {
	    return bean;
    }
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    return beanInstance;
}
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
	Object bean = null;
	Class<?> targetType = determineTargetType(beanName, mbd);
	bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
	if (bean != null) {
		bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
	}
	return bean;
}
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
				if (result != null) {
					return result;
				}
			}
		}
		return null;
	}

调用 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 是接口定义,

由实现类AbstractAutoProxyCreator#postProcessBeforeInstantiation来实现代理对象生成。

//org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
    //生成代理对象
	Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
	return proxy;
}

spring中动态代理的大致流程就是这样,接下来再回头分析下springAOP配置文件的解析工作。

解析的流程依然是以配置文件为例,入口在refreash防范中:

//1 
 //AbstractApplicationContext#refresh
    // Tell the subclass to refresh the internal bean factory.
// 核心加载
	ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

//2
  protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        // 核心加载
		refreshBeanFactory();
		return getBeanFactory();
}

//3
  //AbstractRefreshableApplicationContext#refreshBeanFactory
	protected final void refreshBeanFactory(){
            ...
            // 核心加载
			loadBeanDefinitions(beanFactory);
	}

//4
  //AbstractXmlApplicationContext#loadBeanDefinitions()
	/**
	 * Loads the bean definitions via an XmlBeanDefinitionReader.
	 * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
	 * @see #initBeanDefinitionReader
	 * @see #loadBeanDefinitions
	 */

	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
		// then proceed with actually loading the bean definitions.
// 核心加载
		loadBeanDefinitions(beanDefinitionReader);
	}

	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
            // 核心加载
			reader.loadBeanDefinitions(configLocations);
		}
	}

//5
  //AbstractBeanDefinitionReader#loadBeanDefinitions(...)
	public int loadBeanDefinitions(String... locations) {
		int count = 0;
		for (String location : locations) {
            // 核心加载
			count += loadBeanDefinitions(location);
		}
		return count;
	}


	public int loadBeanDefinitions(String location) {
			// Can only load single resources by absolute URL.
			Resource resource = resourceLoader.getResource(location);
             // 核心加载
			int count = loadBeanDefinitions(resource);
			return count;
		}
	}



//6
  //XmlBeanDefinitionReader#loadBeanDefinitions()

	public int loadBeanDefinitions(EncodedResource encodedResource)  {
		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
		try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
			InputSource inputSource = new InputSource(inputStream);
            // 核心加载
			return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
		}
		catch (IOException ex) {
		}
	}


	protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			 {
			Document doc = doLoadDocument(inputSource, resource);
// 核心加载
			int count = registerBeanDefinitions(doc, resource);
			return count;
	}


	public int registerBeanDefinitions(Document doc, Resource resource){
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		int countBefore = getRegistry().getBeanDefinitionCount();
// 核心加载
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

//7
 // DefaultBeanDefinitionDocumentReader#registerBeanDefinitions
	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
// 核心加载
		doRegisterBeanDefinitions(doc.getDocumentElement());
	}

	protected void doRegisterBeanDefinitions(Element root) {
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent);
		preProcessXml(root);
// 核心加载
		parseBeanDefinitions(root, this.delegate);
		postProcessXml(root);
		this.delegate = parent;
	}

	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {
// 核心加载  默认spring的配置元素
						parseDefaultElement(ele, delegate);
					}
					else {
// 核心加载  自定义的配置元素
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
// 核心加载
			delegate.parseCustomElement(root);
		}
	}

AOP属于自定义的配置元素,接下来分析AOP标签元素的解析过程,由此可知晓BeanDefinition的封装,以及类之间的包含关系。

解析:<aop:config>

//1
 //BeanDefinitionParserDelegate#parseCustomElement(...)
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
		String namespaceUri = getNamespaceURI(ele);
		
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		//核心解析流程
		return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
	}


//2    	org.springframework.beans.factory.xml.NamespaceHandler#parse

//3    	org.springframework.beans.factory.xml.NamespaceHandlerSupport#parse
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		BeanDefinitionParser parser = findParserForElement(element, parserContext);
		return (parser != null ? parser.parse(element, parserContext) : null);
	}

//4    	org.springframework.beans.factory.xml.BeanDefinitionParser#parse

//5	org.springframework.aop.config.ConfigBeanDefinitionParser#parse
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		CompositeComponentDefinition compositeDef =
				new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
		parserContext.pushContainingComponent(compositeDef);
		//核心解析流程 注册自动代理生成器 AspectJAwareAdvisorAutoProxyCreator
		configureAutoProxyCreator(parserContext, element);

		List<Element> childElts = DomUtils.getChildElements(element);
		for (Element elt: childElts) {
			String localName = parserContext.getDelegate().getLocalName(elt);
			if (POINTCUT.equals(localName)) {
				//核心解析流程 
				parsePointcut(elt, parserContext);
			}
			else if (ADVISOR.equals(localName)) {
			//核心解析流程
				parseAdvisor(elt, parserContext);
			}
			else if (ASPECT.equals(localName)) {
			//核心解析流程
				parseAspect(elt, parserContext);
			}
		}

		parserContext.popAndRegisterContainingComponent();
		return null;
	}

	/**
	 * Configures the auto proxy creator needed to support the {@link BeanDefinition BeanDefinitions}
	 * created by the '{@code <aop:config/>}' tag. Will force class proxying if the
	 * '{@code proxy-target-class}' attribute is set to '{@code true}'.
	 * @see AopNamespaceUtils
	 */
	private void configureAutoProxyCreator(ParserContext parserContext, Element element) {
	//核心解析流程
		AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);
	}


	 
// 6 //org.springframework.aop.config.AopNamespaceUtils#registerAspectJAutoProxyCreatorIfNecessary
	public static void registerAspectJAutoProxyCreatorIfNecessary(
			ParserContext parserContext, Element sourceElement) {
        //核心解析流程
		BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary(
				parserContext.getRegistry(), parserContext.extractSource(sourceElement));
		useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
		registerComponentIfNecessary(beanDefinition, parserContext);
	}
	public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {
               //核心解析流程
		return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
	}

Parser解析器的类关系:

 ConfigBeanDefinitionParser 用来解析自定义标签 <aop:config>
AspectJAutoProxyBeanDefinitionParser 用来解析注解 @AspectJ

解析<aop:aspect>的时候,会准备相关材料,需要先充分掌握以下类的关系,才能理解此处的解析:

//一级对象
class AspectJPointcutAdvisor {
	//二级对象
	private final AbstractAspectJAdvice advice;

	private final Pointcut pointcut;

	@Nullable
	private Integer order;

}

//二级对象
class AbstractAspectJAdvice{
	//切面方法
	protected transient Method aspectJAdviceMethod;  
	//切面表达式
	private final AspectJExpressionPointcut pointcut;
	//实例工厂
	private final AspectInstanceFactory aspectInstanceFactory;
}
// org.springframework.aop.config.ConfigBeanDefinitionParser#parseAspect
//1
private void parseAspect(Element aspectElement, ParserContext parserContext) {
		String aspectId = aspectElement.getAttribute(ID);
		String aspectName = aspectElement.getAttribute(REF);

		try {
			this.parseState.push(new AspectEntry(aspectId, aspectName));
			List<BeanDefinition> beanDefinitions = new ArrayList<>();
			List<BeanReference> beanReferences = new ArrayList<>();


			// We have to parse "advice" and all the advice kinds in one loop, to get the
			// ordering semantics right.
			NodeList nodeList = aspectElement.getChildNodes();
			boolean adviceFoundAlready = false;
			for (int i = 0; i < nodeList.getLength(); i++) {
				Node node = nodeList.item(i);
				if (isAdviceNode(node, parserContext)) {
					//核心流程  解析增强
					AbstractBeanDefinition advisorDefinition = parseAdvice(
							aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences);
					beanDefinitions.add(advisorDefinition);
				}
			}

			AspectComponentDefinition aspectComponentDefinition = createAspectComponentDefinition(
					aspectElement, aspectId, beanDefinitions, beanReferences, parserContext);
			parserContext.pushContainingComponent(aspectComponentDefinition);

			List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT);
			for (Element pointcutElement : pointcuts) {
			//核心流程  解析切点
				parsePointcut(pointcutElement, parserContext);
			}

			parserContext.popAndRegisterContainingComponent();
		}
		finally {
			this.parseState.pop();
		}
	}


//2 准备 构造切面对象的三种材料 method;factory;point
	/**
	 * Parses one of '{@code before}', '{@code after}', '{@code after-returning}',
	 * '{@code after-throwing}' or '{@code around}' and registers the resulting
	 * BeanDefinition with the supplied 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)));

			// create the method factory bean
			RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class);
			methodDefinition.getPropertyValues().add("targetBeanName", aspectName);
			methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method"));
			methodDefinition.setSynthetic(true);

			// create instance factory definition
			RootBeanDefinition aspectFactoryDef =
					new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);
			aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName);
			aspectFactoryDef.setSynthetic(true);

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

			// configure the advisor
			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));
			}

			// register the final advisor
			parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);

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

//4
	/**
	 * 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.
	 */
	private AbstractBeanDefinition createAdviceDefinition(
			Element adviceElement, ParserContext parserContext, String aspectName, int order,
			RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef,
			List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值