当系统比较复杂,或者中需要进行aop进行织入的bean较多时,简单采用ProxyFacotryBean无疑会增加很多工作量,同时由于要从ProxyFactoryBean获得代理对象,也会使应用和Spring之间的耦合度增加,并且很多时候可维护性不强,譬如,我们需要给bean名字满足“*service”的bean每个方法增加事务功能,如果采用ProxyFacotryBean必须为每个以service结尾的bean增加一个配置。当然,如果愿意当然可以重复copy-past可以满足,若以后又有人增加了一个bean:Abcservice,这时若他忘记增加对应的ProxyFacotyBean配置,可能导致灾难性的后果。这样的情况下,自动代理的方式就能发挥它巨大的优势了。
1. 使用举例
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames"><value>*service</value></property>
<property name="interceptorNames">
<list>
<value>myInterceptor</value>
</list>
</property>
</bean>
通过配置beanNames属性,beanName是以service结尾时将会织入myInterceptor中指定的横切逻辑。
2. 类结构图

2.1 调用时机
从类结构图中可以看出,AbstractAutoProxyCreator实现了SmartInstantiantionAwareBeanPostProcessor接口,作为一个BeanPostProcessor,它与ProxyFactoryBean的处理时机不同,通过前面的 Spring Bean实例化过程(2),可以知道,InstantiantionAwareBeanPostProcessor这个后置处理器是在bean对象被创建的之前回调用InstantiantionAwareBeanPostProcessor.postProcessBeforeInstantiation()方法,若此方法返回的结果不为null,则会中断后面bean对象的创建过程。InstantiantionAwareBeanPostProcessor.postProcessAfterInstantiation()是在对象被创建之后,属性注入之前,若该方法返回false,会中断属性的注入,并且也会中断InstantiantionAwareBeanPostProcessor链在当前bean上的调用。这里AbstractAutoProxyCreator默认返回true。由于AbstractAutoProxyCreator实现了BeanPostProcessor接口,因此它的调用时机也可以是在属性注入之后,初始化方法调用前后。AbstractAutoProxyCreator给出初始化方法调用之后创建代理对象的实现。
2.2 共同的代理创建逻辑
默认情况下,代理是通过AbstractAutoProxyCreator中的postProcessAfterInitialization()创建的。public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
return bean;
}
b.若earlyProxyReferences缓存中不包含当前cacheKey,则调用wrapIfNecessary()创建代理对象。
earlyProxyReferences这个缓存是干嘛的呢?
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.add(cacheKey);
return wrapIfNecessary(bean, beanName, cacheKey);
}
那么getEarlyBeanReference()方法又是何时被调用的呢?
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (this.nonAdvisedBeans.contains(cacheKey)) {
return bean;
}
if (isInfrastructureClass(bean.getClass(), beanName) || shouldSkip(bean.getClass(), beanName)) {
this.nonAdvisedBeans.add(cacheKey);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.add(cacheKey);
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.nonAdvisedBeans.add(cacheKey);
return bean;
}
执行逻辑解析:
a. 判断bean是否在postProcessBeforeInstantiation()中,即在bean对象创建之前已经被创建代理,在postProcessBeforeInstantiation()中成功创建的代理对象都会将beanName加入到targetSourceBeans中。
b.对于实现了Advice,Advisor,AopInfrastructureBean接口的bean,都认为是spring aop的基础框架类,不能对他们创建代理对象,同时子类也可以覆盖shouldSkip方法来指定不对哪些bean进行代理。
c.调用getAdvicesAndAdvisorsForBean()方法判断当前bean是否需要进行代理,若需要则返回满足条件的Advice或者Advisor集合。根据getAdvicesAndAdvisorsForBean()方法的具体实现的不同,AbstractAutoProxyCreator又分成了两类自动代理机制。
d.若需要代理,则调用createProxy方法创建代理对象,并将创建的代理的key缓存起来,避免重复创建
protected Object createProxy(
Class beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
ProxyFactory proxyFactory = new ProxyFactory();
// Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
proxyFactory.copyFrom(this);
if (!shouldProxyTargetClass(beanClass, beanName)) {
// Must allow for introductions; can't just set interfaces to
// the target's interfaces only.
Class[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);
for (int i = 0; i < targetInterfaces.length; i++) {
proxyFactory.addInterface(targetInterfaces[i]);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (int i = 0; i < advisors.length; i++) {
proxyFactory.addAdvisor(advisors[i]);
}
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(this.proxyClassLoader);
}
从createProxy的代码中可以看到,这里是采用ProxyFactory来进行代理创建,ProxyFacotry的类结构图在Spring AOP之基于ProxyFactoryBean的代理中已经介绍过,这个方法的主要逻辑是
a.创建ProxyFactory实例,并复制当前类的相关配置,
b.然后检查当前类是否有实现基于类的代理,还是基于接口,以此来决定是否采用cglib来创建代理对象。
c.整理合并Advisor,这里AbstractAutoProxyCreator定义了属性interceptorNames用于设置拦截器,同时子类通过getAdvicesAndAdvisorsForBean()方法也可以返回一组Advisor,buildAdvisors()方法就是整理合并这些切面。至于调用的先后顺序,通过applyCommonInterceptorsFirst参数可以进行设置,若applyCommonInterceptorsFirst为true,interceptorNames属性指定的Advisor优先调用。默认为true;
d通过customizeProxyFactory()方法,子类可以对proxyFactory进行设置更改。
e.最后调用proxyFactory.getProxy()方法返回代理对象。
2.3 两类自动代理
AbstractAutoProxyCreator有两个子类,一个是BeanNameAutoProxyCreator,它是基于bean名字的自动代理类。
它会给spring容器中bean名字与指定名字匹配的bean自动创建代理。其中匹配的规则定义在PatternMatchUtils.simpleMatch()方法中。注意:若需要给某个FactoryBean创建代理,可以在bean名字前面加上&.
第二类是AbstractAdvisorAutoProxyCreator,相对BeanNameAutoProxyCreator而言,它更为强大,它会自动获取spring容器中注册的所有的Advisor类(除了子类中isEligibleAdvisorBean()方法指定的不满足条件的Advisor除外。),然后自动给spring容器中满足Advisor中pointCut创建代理。
DefaultAdvisorAutoProxyCreator是默认实现,默认会自动代理所有的Advisor,当然也可以通过设置usePrefix和advisorBeanNamePrefix来过滤部分advisor
AspectJAwareAdvisorAutoProxyCreator用于支持AspectJ方式的自动代理。