注意:我们分析的版本是SpringFramework-3.2.8.RELEASE。
先上一张图,如下图1所示,后面会用到:
图1 BeanNameAutoProxyCreator间接继承了BeanPostProcessor
类Seller、Waiter、GreetingBeforeAdvice的代码如下,先做下铺垫:
public class Seller {
public void greetTo(String name) {
LOG.info("Seller greet to: {}", name);
}
}
public class Waiter {
public void greetTo(String name){
LOG.info("waiter greet to: {}",name);
}
public void serveTo(String name){
LOG.info("waiter serving to: {}",name);
}
}
import org.springframework.aop.MethodBeforeAdvice;
import com.mjduan.project.log.LOG;
/**
* @author mjduan@yahoo.com 2018-05-03 13:20
* @version 0.0.1
* @since 0.0.1
*/
public class GreetingBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
LOG.info("Greeting before advice: {}", args[0]);
}
}
spring的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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:component-scan base-package="com.mjduan.project"/>
<bean id="seller" class="com.mjduan.project.example4.Seller"/>
<bean id="waiter" class="com.mjduan.project.example4.Waiter"/>
<bean id="greetingAdvice" class="com.mjduan.project.example4.GreetingBeforeAdvice"/>
<bean id="beanNameAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames" value="*er"/>
<property name="interceptorNames" value="greetingAdvice"/>
<property name="optimize" value="true"/>
</bean>
</beans>
单元测试代码如下:
@Test
public void test1(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring4.xml");
Waiter waiter = applicationContext.getBean("waiter", Waiter.class);
Seller seller = applicationContext.getBean("seller", Seller.class);
waiter.greetTo("John");
seller.greetTo("Tom");
}
到这里,铺垫基本是完成了,下面开始分析。
上面的单元测试代码中waiter、seller其实是Cglib生成的代理对象,这个可以自己打断点查看。
先说明下BeanPostProcessor的postProcessAfterInitialization(...)的作用,因为这个是后面内容的铺垫。假设Spring容器中beanNameX对应的bean是A,那么经过某个类(这个类实现了BeanPostProcessor接口)的postProcessAfterInitialization(A,beanNameX)处理后返回B,则此时Spring容器中beanNameX对应的bean是B,而不是A。
在AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsAfterInitialization中,会调用BeanPostProcessor的postProcessAfterInitialization。
AbstractAutowireCapableBeanFactory调用BeanNameAutoProxyCreator的图如下图2所示,有些步骤被我省略了,主要集中与主流程,因为分支太多了,难以全部遍及。
图2 AbstractAutowireCapableBeanFactory调用BeanNameAutoProxyCreator
applicationContext.getBean("waiter", Waiter.class)时,会调用BeanNameAutoProxyCreator的postProcessAfterInitialization,如图2的步骤1,这个方法返回的对象就是用Cglib生成的代理对象waiter,所以我们从Spring中拿到的是代理类,而不是waiter对象。如下所示,wrapIfNecessary方法里面的就是我们重点分析的内容。
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.containsKey(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
步骤3中的getAdvicesAndAdvisorsForBean方法,就是判断是否需要被代理的逻辑代码,这里不再分析。
步骤4中,通过ProxyFactory的getProxy(),来生成代理类。
从Spring容器中拿到的Seller,是由Cglib生成的代理对象,同上述的Waiter。
GreetingBeforeAdvice在waiter.greetTo()和seller.greetTo()的前调用是如何实现的?这个与ProxyFactory的advisor有关,图2的步骤4中有涉及。
我们在spring xml配置文件中定义了BeanNameAutoProxyCreator,并未对其设置什么,Spring是如何调用它的方法postProcessAfterInitialization? 来看下AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsAfterInitialization实现,如下所示:
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
首先从容器中取出所有的BeanPostProcessor,逐个对其调用postProcessAfterInitialization,而我们的BeanNameAutoProxyCreator恰好是BeanPostProcessor,所以在这里BeanNameAutoProxyCreator的postProcessAfterInitialization就会被调用到。
(adsbygoogle = window.adsbygoogle || []).push({});