Spring AOP工作机制进一步理解(下篇)

        前面通过源码,分析了<aop:aspectj-autoproxy>、<aop:config>配置下的spring AOP工作机制,本文分析AutoProxyCreator、ProxyFactoryBean配置下的工作机制。

BeanNameAutoProxyCreator

Spring xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:aop="http://www.springframework.org/schema/aop" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
						http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
						http://www.springframework.org/schema/context  
						http://www.springframework.org/schema/context/spring-context-3.0.xsd
						http://www.springframework.org/schema/aop
						http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
	<!-- 用户业务逻辑bean -->
  	<bean id="userAction" class="org.test.aop.UserAction"/>

	<!-- MethodBeforeAdvice bean -->
	<bean id="aopMethodBeforeAdvice" class="org.test.aop.AopMethodBeforeAdvice"/>
 
	<!-- BeanNameAutoProxyCreator配置 -->
	<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
		<property name="beanNames">
			<value>
				*Action
			</value>
		</property>
		<property name="interceptorNames">
			<value>aopMethodBeforeAdvice</value>
		</property>
		<property name="optimize">
			<value>true</value>
		</property>
	</bean>

</beans>

解析

       xml配置中的BeanNameAutoProxyCreator、AopMethodBeforeAdvice都是以bean的形式解析,且注册到beanFactory,详见 《Spring ioc容器启动流程—obtainFreshBeanFactory》

生成代理对象

BeanNameAutoProxyCreator对象实例化

       AbstractAutoProxyCreator实现了BeanPostProcessor接口,BeanPostProcessor对象实例化发生在AbstractApplicationContext.refresh()的registerBeanPostProcessors步骤。在所有AOP的配置中,这点是一样的。

BeanNameAutoProxyCreator生成代理类实例

       与<aop:config>方式基本流程一样。区别在于,BeanNameAutoProxyCreator配置在AbstractAutoProxyCreator.createProxy的buildAdvisors步骤中获取Advisors的方式:

/** AbstractAutoProxyCreator.java */
// 获取Advisors,用于AOP拦截机制
protected Advisor[] buildAdvisors(String beanName, Object[] specificInterceptors) {
	// BeanNameAutoProxyCreator配置在resolveInterceptorNames中实例化PointcutAdvisor,且为DefaultPointcutAdvisor
	Advisor[] commonInterceptors = resolveInterceptorNames();

	List<Object> allInterceptors = new ArrayList<Object>();
	// BeanNameAutoProxyCreator配置下specificInterceptors的length为0
	if (specificInterceptors != null) {
		allInterceptors.addAll(Arrays.asList(specificInterceptors));
		if (commonInterceptors != null) {
			if (this.applyCommonInterceptorsFirst) {
				allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
			}
			else {
				allInterceptors.addAll(Arrays.asList(commonInterceptors));
			}
		}
	}
	if (logger.isDebugEnabled()) {
		int nrOfCommonInterceptors = (commonInterceptors != null ? commonInterceptors.length : 0);
		int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
		logger.debug("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
				" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
	}

	Advisor[] advisors = new Advisor[allInterceptors.size()];
	for (int i = 0; i < allInterceptors.size(); i++) {
		advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
	}
	return advisors;
}

// BeanNameAutoProxyCreator中显示指明interceptorNames属性,根据interceptor的名称实例化Advice,包装为DefaultPointcutAdvisor
private Advisor[] resolveInterceptorNames() {
	ConfigurableBeanFactory cbf = (this.beanFactory instanceof ConfigurableBeanFactory) ?
			(ConfigurableBeanFactory) this.beanFactory : null;
	List<Advisor> advisors = new ArrayList<Advisor>();
	for (String beanName : this.interceptorNames) {
		if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
			Object next = this.beanFactory.getBean(beanName);
			advisors.add(this.advisorAdapterRegistry.wrap(next));
		}
	}
	return advisors.toArray(new Advisor[advisors.size()]);
}

DefaultAdvisorAutoProxyCreator

Spring xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:aop="http://www.springframework.org/schema/aop" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
						http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
						http://www.springframework.org/schema/context  
						http://www.springframework.org/schema/context/spring-context-3.0.xsd
						http://www.springframework.org/schema/aop
						http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
  	<!-- 用户业务逻辑bean -->
	<bean id="userAction" class="org.test.aop.UserAction"/>

	<!-- MethodBeforeAdvice bean -->
	<bean id="aopMethodBeforeAdvice" class="org.test.aop.AopMethodBeforeAdvice"/>

	<!-- DefaultAdvisorAutoProxyCreator配置 -->
	<bean id="regexpAdvisor2" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
		<property name="pattern">
			<value>.*modiUser.*</value>
		</property>
		<property name="advice" ref="aopMethodBeforeAdvice">
		</property>
	</bean>
	<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
              
</beans>

解析

        xml配置中的DefaultAdvisorAutoProxyCreator、RegexpMethodPointcutAdvisor、AopMethodBeforeAdvice都是以bean的形式解析,且注册到beanFactory。  

生成代理对象

DefaultAdvisorAutoProxyCreator生成代理类实例

       与<aop:config>方式一样。

        BeanNameAutoProxyCreator配置下的PointcutAdvisor实例化在AbstractAutoProxyCreator.buildAdvisors中发生、DefaultAdvisorAutoProxyCreator配置下的PointcutAdvisor实例化在AbstractAutoProxyCreator.getAdvicesAndAdvisorsForBean中发生,都是在AbstractAutoProxyCreator.postProcessAfterInitialization过程中完成。

ProxyFactoryBean

Spring xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:aop="http://www.springframework.org/schema/aop" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
						http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
						http://www.springframework.org/schema/context  
						http://www.springframework.org/schema/context/spring-context-3.0.xsd
						http://www.springframework.org/schema/aop
						http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">		
	<!-- 用户业务逻辑bean --> 
	<bean id="impl" class="org.test.aop.AopImpl"/>
	<!-- aroundInterceptor bean --> 
	<bean id="aroundInterceptor" class="org.test.aop.AopAroundInterceptor"/>  
	<!-- beforeInterceptor bean --> 	
	<bean id="beforeInterceptor" class="org.test.aop.AopBeforeInterceptor"/>  	
	<bean id="beforePatternInterceptor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
		<property name="advice">  
			<ref bean="beforeInterceptor"/>  
		</property>  
	 
		<property name="patterns">  
			<value>.*doabc.* </value>  
		</property>  
	</bean>   
	<!-- ProxyFactoryBean配置 --> 
	<bean id="proxyFactoryBean" 
	    class="org.springframework.aop.framework.ProxyFactoryBean">
	    <property name="proxyInterfaces">
	        <value>
	            org.test.aop.AopInterface
	        </value>
	    </property>
	    <property name="target"><ref local="impl"></ref> </property>
	    <property name="singleton"><value>true</value></property>
	    <property name="interceptorNames">
	        <list>
	        	<value>beforePatternInterceptor</value>
	            <value>aroundInterceptor</value>
	        </list>
	    </property>
	</bean>
             
</beans>

解析

        xml配置中的AopAroundInterceptor、RegexpMethodPointcutAdvisor、ProxyFactoryBean都是以bean的形式解析,且注册到beanFactory。

ProxyFactoryBean类结构继承图:


生成代理对象

         ProxyFactoryBean是FactoryBean,从其getObject()获取的Object是代理对象:

/** ProxyFactoryBean.java */
// 获取代理对象
public Object getObject() throws BeansException {
	// 实例化advice
	initializeAdvisorChain();
	if (isSingleton()) {
		// 获取Singleton代理对象
		return getSingletonInstance();
	}
	else {
		if (this.targetName == null) {
			logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
					"Enable prototype proxies by setting the 'targetName' property.");
		}
		// 获取Prototype代理对象
		return newPrototypeInstance();
	}
}

private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
	if (this.advisorChainInitialized) {
		return;
	}

	if (!ObjectUtils.isEmpty(this.interceptorNames)) {
		if (this.beanFactory == null) {
			throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
					"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
		}

		// Globals can't be last unless we specified a targetSource using the property...
		if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
				this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
			throw new AopConfigException("Target required after globals");
		}

		// Materialize interceptor chain from bean names.
		for (String name : this.interceptorNames) {
			if (logger.isTraceEnabled()) {
				logger.trace("Configuring advisor or advice '" + name + "'");
			}

			if (name.endsWith(GLOBAL_SUFFIX)) {
				if (!(this.beanFactory instanceof ListableBeanFactory)) {
					throw new AopConfigException(
							"Can only use global advisors or interceptors with a ListableBeanFactory");
				}
				addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
						name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
			}

			else {
				// If we get here, we need to add a named interceptor.
				// We must check if it's a singleton or prototype.
				Object advice;
				if (this.singleton || this.beanFactory.isSingleton(name)) {
					// 实例化Advice
					advice = this.beanFactory.getBean(name);
				}
				else {
					// It's a prototype Advice or Advisor: replace with a prototype.
					// Avoid unnecessary creation of prototype bean just for advisor chain initialization.
					advice = new PrototypePlaceholderAdvisor(name);
				}
				addAdvisorOnChainCreation(advice, name); // Advice转化为Advisor
			}
		}
	}

	this.advisorChainInitialized = true;
}

// 创建代理对象
private synchronized Object getSingletonInstance() {
	if (this.singletonInstance == null) {
		this.targetSource = freshTargetSource();
		if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
			// Rely on AOP infrastructure to tell us what interfaces to proxy.
			Class targetClass = getTargetClass();
			if (targetClass == null) {
				throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
			}
			setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
		}
		// Initialize the shared singleton instance.
		super.setFrozen(this.freezeProxy);
		this.singletonInstance = getProxy(createAopProxy());
	}
	return this.singletonInstance;
}	

       <aop:aspectj-autoproxy>、<aop:config>、AutoProxyCreator、ProxyFactoryBean是spring AOP几种不同的应用场景,但AOP的核心流程一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值