注意:咱们分析的版本是SpringFramework-3.2.8.RELEASE。java
先上一张图,以下图1所示,后面会用到:spring
图1 BeanNameAutoProxyCreator间接继承了BeanPostProcessorapp
类Seller、Waiter、GreetingBeforeAdvice的代码以下,先作下铺垫:ide
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配置以下:post
<?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生成的代理对象,这个能够本身打断点查看。this
先说明下BeanPostProcessor的postProcessAfterInitialization(...)的做用,由于这个是后面内容的铺垫。假设Spring容器中beanNameX对应的bean是A,那么通过某个类(这个类实现了BeanPostProcessor接口)的postProcessAfterInitialization(A,beanNameX)处理后返回B,则此时Spring容器中beanNameX对应的bean是B,而不是A。spa
在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就会被调用到。