spring-mvc源碼-bean定義加載-非默認標籤解析(tx:annotation-driven)

<tx:annotation-driven />這個標籤對應的處理器是TxNamespaceHandler,對應的解析器是AnnotationDrivenBeanDefinitionParser,parse方法如下:

	public BeanDefinition parse(Element element, ParserContext parserContext) {
		//註冊事務監聽器工廠
		registerTransactionalEventListenerFactory(parserContext);
		String mode = element.getAttribute("mode");
		if ("aspectj".equals(mode)) {
			// mode="aspectj"
			//註冊事務切面,
			registerTransactionAspect(element, parserContext);
		}
		else {
			// mode="proxy"
			//創建自動代理器
			AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
		}
		return null;
	}

註冊事務切面方法registerTransactionAspect:

	private void registerTransactionAspect(Element element, ParserContext parserContext) {
		String txAspectBeanName = TransactionManagementConfigUtils.TRANSACTION_ASPECT_BEAN_NAME;
		String txAspectClassName = TransactionManagementConfigUtils.TRANSACTION_ASPECT_CLASS_NAME;
		if (!parserContext.getRegistry().containsBeanDefinition(txAspectBeanName)) {
			RootBeanDefinition def = new RootBeanDefinition();
			def.setBeanClassName(txAspectClassName);
			def.setFactoryMethodName("aspectOf");
			//註冊事務管理器到bean定義
			registerTransactionManager(element, def);
			//註冊事務管理器切面bean定義
			parserContext.registerBeanComponent(new BeanComponentDefinition(def, txAspectBeanName));
		}
	}

創建自動代理器方法configureAutoProxyCreator:

		public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
			//註冊自動代理創建器
			AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

			String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
			if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
				Object eleSource = parserContext.extractSource(element);

				//創建AnnotationTransactionAttributeSource的BeanDefinition
				RootBeanDefinition sourceDef = new RootBeanDefinition(
						"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
				sourceDef.setSource(eleSource);
				sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
				String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

				//創建TransactionInterceptor的BeanDefinition
				RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
				interceptorDef.setSource(eleSource);
				interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
				//註冊事務管理器 也就是獲取transaction-manager這個屬性的值,如果未指定,默認是transactionManager
				registerTransactionManager(element, interceptorDef);
				interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
				String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);

				//創建BeanFactoryTransactionAttributeSourceAdvisor的BeanDefinition
				RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
				advisorDef.setSource(eleSource);
				advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
				advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
				advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
				if (element.hasAttribute("order")) {
					advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
				}
				parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);

				CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
				compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
				compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
				compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
				parserContext.registerComponent(compositeDef);
			}
		}

這個方法很長,但結構很清晰,分別註冊了三個BeanDefinition,分別爲AnnotationTransactionAttributeSource、TransactionInterceptor和BeanFactoryTransactionAttributeSourceAdvisor,將第一個BeanDefinition添加到了第二個BeanDefinition的屬性中,然後將前兩個BeanDefinition添加到第三個BeanDefinition的屬性當中,這三個bean支撐了整個事務功能。


接下來看下注冊自動代理創建器方法:AopAutoProxyConfigurer.configureAutoProxyCreator:

	public static void registerAutoProxyCreatorIfNecessary(
			ParserContext parserContext, Element sourceElement) {
		//註冊代理創建器
		BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(
				parserContext.getRegistry(), parserContext.extractSource(sourceElement));
		//設置proxy-target-class和expose-proxy屬性
		//Spring提供了JDK動態代理和CGLIB代理兩種方式爲目標類創建代理,默認情況下,如果目標類實現了一個以上的用戶自定義的接口或者目標類本身就是接口,就會使用JDK動態代理,如果目標類本身不是接口並且沒有實現任何接口,就會使用CGLIB代理,
		//如果想強制使用CGLIB代理,則可以將proxy-target-class設置true,這兩種代理方式在使用的時候有一些需要注意的事項,JDK動態代理是基於實現目標類的接口來創建代理類的,所以只有接口方法會被代理,其他方法不會被代理,
		//而CGLIB代理是基於繼承目標類實現的,所以不能被繼承的方法(例如final修飾的方法、private修飾的方法等)是不能被代理的,建議儘量使用JDK動態代理的方式創建代理類。
		//expose-proxy用來解決對象內部this調用無法被切面增強的問題,例如我們在A類的對象內部x方法中調用另外一個內部方法y時,y方法不會被切面增強,這時可以配置expose-proxy爲true並將this.y()改爲((A)AopContext.currentProxy()).y(),
		//即可讓y方法被切面增強
		useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
		registerComponentIfNecessary(beanDefinition, parserContext);
	}

然後調了org.springframework.aop.config.AopConfigUtils#registerAutoProxyCreatorIfNecessary(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)這個方法註冊代理創建器,接着在調org.springframework.aop.config.AopConfigUtils#registerOrEscalateApcAsRequired這個方法

	private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			//判斷已存在的代理創建器和本次要註冊的代理創建器是否是相同的
			if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
				//獲取已經存在的代理創建器的優先級
				int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
				//獲取本次要創建的代理創建器的優先級
				int requiredPriority = findPriorityForClass(cls);
				//判斷優先級,使用優先級高的代理創建器
				if (currentPriority < requiredPriority) {
					apcDefinition.setBeanClassName(cls.getName());
				}
			}
			//如果是相同的直接返回無需再次註冊
			return null;
		}
		RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
		beanDefinition.setSource(source);
		//這裏有一個order屬性,設置的值爲Integer.MIN_VALUE,越小越先執行
    	//表示這個RootBeanDefinition要最早被實例化
		beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
		beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		//註冊代理創建器
		registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
		return beanDefinition;
	}

我們上面提到了一個優先級的東西,那這個優先級是在哪兒定義的呢?在AopConfigUtils的靜態塊中有這樣的一段代碼:

	static {
		APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
		APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
		APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
	}

在AopConfigUtils初始化的時候就會向APC_PRIORITY_LIST中添加這三個Class類。而上面提到的優先級就是他們在APC_PRIORITY_LIST中的位置。由此可見AspectJAwareAdvisorAutoProxyCreator會覆蓋InfrastructureAdvisorAutoProxyCreatorBeanDefinition中的class,而AnnotationAwareAspectJAutoProxyCreator又會覆蓋AspectJAwareAdvisorAutoProxyCreator的BeanDefinition中的class(當然也會覆蓋InfrastructureAdvisorAutoProxyCreator的BeanDefinition)。

InfrastructureAdvisorAutoProxyCreator是一個基礎建設性的類,即識別不使用@Aspect註解的AOP配置(比如事務的實現);AspectJAwareAdvisorAutoProxyCreator在<aop:config/>這個配置時用的;AnnotationAwareAspectJAutoProxyCreator在<aop:aspectj-autoproxy/>這個配置時用的,並在AspectjAwareAdvisorAutoProxyCreator的基礎上增加了對註解@Aspect的支持。

這裏註冊的代理創建器就是InfrastructureAdvisorAutoProxyCreator,看下它的繼承結構:

我們發現這個類間接實現了BeanPostProcessor接口,我們知道,Spring會保證所有bean在實例化的時候都會調用其postProcessAfterInitialization方法,我們可以使用這個方法包裝和改變bean,而真正實現這個方法是在其父類AbstractAutoProxyCreator類中,這部分更細節的在介紹aop的時候,再細說。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章