Spring源码-从源码层面讲解声明式事务配置文件的加载和相关对象的创建1(创建对向,属性填充,动态代理均有涉及)

tx.xml事务配置文件的解析

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    <context:property-placeholder location="classpath:dbconfig.properties"></context:property-placeholder>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="driverClassName" value="${jdbc.driverClassName}"></property>
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" >
        <constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
    </bean>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <bean id="bookService" class="com.study.spring.tx.xml.service.BookService">
        <property name="bookDao" ref="bookDao"></property>
    </bean>
    <bean id="bookDao" class="com.study.spring.tx.xml.dao.BookDao">
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>
    <aop:config>
        <aop:pointcut id="txPoint" expression="execution(* com.study.spring.tx.xml.*.*.*(..))"/>
        <aop:advisor advice-ref="myAdvice" pointcut-ref="txPoint"></aop:advisor>
    </aop:config>
    <tx:advice id="myAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="checkout" propagation="REQUIRED" />
            <tx:method name="updateStock" propagation="REQUIRES_NEW" />
        </tx:attributes>
    </tx:advice>
  <!--  <bean class="com.study.spring.MyBeanFactoryPostProcessorBySelf"></bean>-->
</beans>

PlaceholderConfigurerSupport类

spring提供的一个工具类,用于解析bean定义中属性值里面的占位符,此类不能被直接实例化使用
public abstract class PlaceholderConfigurerSupport extends PropertyResourceConfigurer
		implements BeanNameAware, BeanFactoryAware 

会把 > <context:property-placeholder location=“classpath:dbconfig.properties”></context:property-placeholder>
这个标签解析替换${jdbc.username}这样的内容

aop标签解析

    <aop:config>
        <aop:pointcut id="txPoint" expression="execution(* com.study.spring.tx.xml.*.*.*(..))"/>
        <aop:advisor advice-ref="myAdvice" pointcut-ref="txPoint"></aop:advisor>
    </aop:config>

根据标签名找到对应的handler
在这里插入图片描述

在这里插入图片描述

http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler
AOP命名空间解析类。我们在用AOP的时候,会在Spring配置文件的beans标签中引入:xmlns:aop
public class AopNamespaceHandler extends NamespaceHandlerSupport {
   
   

	@Override
	public void init() {
   
   
		// In 2.0 XSD as well as in 2.5+ XSDs
		registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
		registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
		registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

		// Only in 2.0 XSD: moved to context namespace in 2.5+
		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
	}

}
	/**解析自定义元素(在默认名称空间之外)。
	 * @param containingBd the containing bean definition (if any) @param containingBd包含bean的定义(如果有的话)
	 * @return the resulting bean definition 得到的bean定义
	 */
	@Nullable
	public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
   
   
		// 获取对应的命名空间
		String namespaceUri = getNamespaceURI(ele);
		if (namespaceUri == null) {
   
   
			return null;
		}
		// 根据命名空间找到对应的NamespaceHandlerspring
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		if (handler == null) {
   
   
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
			return null;
		}
		// 调用自定义的NamespaceHandler进行解析 NamespaceHandlerSupport
		return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
	}

handler.parse调用的是NamespaceHandlerSupport的parse方法,因为AopNamespaceHandler extends NamespaceHandlerSupport

	/**
	 * 通过委托为{@link Element}注册的{@link BeanDefinitionParser}来解析提供的{@link Element}。
	 */
	@Override
	@Nullable
	public BeanDefinition parse(Element element, ParserContext parserContext) {
   
   
		// 获取元素的解析器
		BeanDefinitionParser parser = findParserForElement(element, parserContext);
		return (parser != null ? parser.parse(element, parserContext) : null);//ComponentScanBeanDefinitionParser的方法
	}

parser是ConfigBeanDefinitionParser:

	public BeanDefinition parse(Element element, ParserContext parserContext) {
   
   
		CompositeComponentDefinition compositeDef =
				new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
		parserContext.pushContainingComponent(compositeDef);
// 注册自动代理模式创建器,AspectjAwareAdvisorAutoProxyCreator 配置文件注解混合使用 context:commponentScan 注入innteral的类 这里也注入类似的类
		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;
	}

configureAutoProxyCreator(parserContext, element);的功能是AspectJAwareAdvisorAutoProxyCreator引入。

pointcut 和 advisor 标签会在parsePointcut(elt, parserContext);和parseAdvisor(elt, parserContext);方法解析生成bean对象。
**parsePointcut(elt, parserContext);**最终createPointcutDefinition:

	/**
	 * Creates a {@link BeanDefinition} for the {@link AspectJExpressionPointcut} class using
	 * the supplied pointcut expression.
	 */
	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;
	}
<aop:pointcut id="txPoint" expression="execution(* com.study.spring.tx.xml.*.*.*(..))"/>对应AspectJExpressionPointcut

**parseAdvisor(elt, parserContext);**最终调用createAdvisorBeanDefinition:

	/**
	 * 解析advisor顾问类
	 *
	 * Parses the supplied {@code <advisor>} element and registers the resulting
	 * {@link org.springframework.aop.Advisor} and any resulting {@link org.springframework.aop.Pointcut}
	 * with the supplied {@link BeanDefinitionRegistry}.
	 */
	private void parseAdvisor(Element advisorElement, ParserContext parserContext) {
   
   
		// 解析<aop:advisor>节点,最终创建的beanClass为`DefaultBeanFactoryPointcutAdvisor`
		// 另外advice-ref属性必须定义,其与内部属性adviceBeanName对应
		AbstractBeanDefinition advisorDef = createAdvisorBeanDefinition(advisorElement, parserContext);
		String id = advisorElement.getAttribute(ID);

		try {
   
   
			// 注册到bean工厂
			this.parseState.push(new AdvisorEntry(id));
			String advisorBeanName = id;
			if (StringUtils.hasText(advisorBeanName)) {
   
   
				parserContext.getRegistry().registerBeanDefinition(advisorBeanName, advisorDef);
			}
			else {
   
   
				advisorBeanName = parserContext.getReaderContext().registerWithGeneratedName(advisorDef);
			}

			// 解析point-cut属性并赋值到DefaultBeanFactoryPointcutAdvisor#pointcut内部属性
			Object pointcut = parsePointcutProperty(advisorElement, parserContext);
			if (pointcut instanceof BeanDefinition) {
   
   
				advisorDef.getPropertyValues().add(POINTCUT, pointcut);
				parserContext.registerComponent(
						new AdvisorComponentDefinition(advisorBeanName, advisorDef, (BeanDefinition) pointcut));
			}
			else if (pointcut instanceof String) {
   
   
				advisorDef.getPropertyValues().add(POINTCUT, new RuntimeBeanReference((String) pointcut));
				parserContext.registerComponent(
						new AdvisorComponentDefinition(advisorBeanName, advisorDef));
			}
		}
		finally {
   
   
			this.parseState.pop();
		}
	}

	/**
	 * Create a {@link RootBeanDefinition} for the advisor described in the supplied. Does <strong>not</strong>
	 * parse any associated '{@code pointcut}' or '{@code pointcut-ref}' attributes.
	 */
	private AbstractBeanDefinition createAdvisorBeanDefinition(Element advisorElement, ParserContext parserContext) {
   
   
		RootBeanDefinition advisorDefinition = new RootBeanDefinition(DefaultBeanFactoryPointcutAdvisor.class);
		advisorDefinition.setSource(parserContext.extractSource(advisorElement));

		String adviceRef = advisorElement.getAttribute(ADVICE_REF);
		if (!StringUtils.hasText(adviceRef)) {
   
   
			parserContext.getReaderContext().error(
					"'ad
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值