前面通过源码,分析了<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的核心流程一样。