在此之前写了2篇博客,分析了springIOC容器初始化的过程和spring Bean依赖注入的过程,spring在初始化时还做了很多事情,比如注册执行BeanFactoryPostProcessor,注册
BeanPostPorcessor。本篇文章主要就是为了分析这俩点,还有bean依赖注入过程中Bean的初始化。
用过spring的都知道,在定义bean的时候可以指定init-method属性,让bean实例化之后,根据此方法进行初始化。其实除了指定init-method方法,还有其它的方式在bean初始化前
后进行处理。个人知道的有实现InitializingBean,BeanFactoryPostProcessor,BeanPostProcessor有这三种。当然实现Aware接口也可以,但是官方文档中说的
Spring提供了一系列的Aware接口使得bean可以从容器获取需要的资源,个人觉得不适合来控制bean的初始化。
InitializingBean:bean实现此接口后bean在实例化之后会调用afterPropertiesSet()方法。
BeanFactoryPostProcessor:在spring容器加载了bean的定义文件,将其解析成BeanDefinition之后,在bean实例化之前执行的。我们在通过spring配置数据源时,
一般把数据源的具体信息写在一个配置文件中,然后用${url}的形式注入进去。将${url}替换成我们配置里的值就是通过Spring内置的一个BeanFactoryPost,
PropertyPlaceholderConfigurer来实现的。
BeanPostProcessor:定义了俩个方法。postProcessBeforeInitialization()方法在初始化之前执行,postProcessAfterInitialization在初始化之后执行。
1.javaBean
package vo; import org.springframework.beans.factory.InitializingBean; public class User implements InitializingBean { private String name; public void init() { System.out.println("调用了init---" + "原来的name为" + name + "name设置为init"); name = "init"; } public void setName(String name) { this.name = name; } public String getName() { return name; } @Override public void afterPropertiesSet() throws Exception { System.out.println("调用了afterPropertiesSet---" + "原来的name为" + name + "name设置为afterPropertiesSet"); name = "afterPropertiesSet"; } @Override public String toString() { return "User [name=" + name + "]"; } } 2.自定义一个BeanFactoryPostProcessor
package vo; import org.springframework.beans.BeansException; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.TypedStringValue; public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { BeanDefinition bd = beanFactory.getBeanDefinition("user"); MutablePropertyValues mpv = bd.getPropertyValues(); if (mpv.contains("name")) { String oldName=((TypedStringValue) mpv.getPropertyValue("name").getValue()).getValue(); System.out.println("调用了MyBeanFactoryPostProcessor---"+"原来的name为"+oldName+"将name设置为:MyBeanFactoryPostProcessor"); mpv.addPropertyValue("name", "MyBeanFactoryPostProcessor"); } } } 3.自定义一个BeanPostProcessor
package vo; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class MyBeanPostProcessor implements BeanPostProcessor{ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("调用了postProcessBeforeInitialization---------beanName:"+beanName+"---bean:"+bean+"将name设置为MyBeanPostProcessor-Befor"); if("user".equals(beanName)){ User user = (User) bean; user.setName("MyBeanPostProcessor-Before"); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("调用了postProcessAfterInitialization----------beanName:"+beanName+"---bean:"+bean+"将name设置为MyBeanPostProcessor-After"); if("user".equals(beanName)){ User user = (User) bean; user.setName("MyBeanPostProcessor-After"); } return bean; } } 4.配置文件
<?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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd "> <!-- 配置bean --> <bean id="user" class="vo.User" lazy-init="true" init-method="init"> <property name="name" value="czy" /> </bean> <bean id="myBeanFactoryPostProcessor" class="vo.MyBeanFactoryPostProcessor" /> <bean id="myBeanPostProcessor" class="vo.MyBeanPostProcessor"/> </beans> 5.测试代码
package vo; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Services { public static void main(String[] args) { @SuppressWarnings("resource") ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml"); User u = (User) ctx.getBean("user"); System.out.println("用户拿到的name:"+u.getName()); } } 6.输出结果
调用了MyBeanFactoryPostProcessor---原来的name为czy将name设置为:MyBeanFactoryPostProcessor 调用了postProcessBeforeInitialization---------beanName:user---bean:User [name=MyBeanFactoryPostProcessor]将name设置为MyBeanPostProcessor-Befor 调用了afterPropertiesSet---原来的name为MyBeanPostProcessor-Beforename设置为afterPropertiesSet 调用了init---原来的name为afterPropertiesSetname设置为init 调用了postProcessAfterInitialization----------beanName:user---bean:User [name=init]将name设置为MyBeanPostProcessor-After 用户拿到的name:MyBeanPostProcessor-After
7.分析结果 3)执行InitializingBean接口的afterPropertiesSet() 5)执行BeanPostProcessor的postProcessAfterInitialization方法。
可以把断点打在getBean()方法上,会发现控制台已经输出了上面的第一句化,说明BeanFactoryPostProcessor是在Bean实例化之前执行,BeanFactoryPostProcessor在spring加载了bean的定义文件在调试的时候可以。从最终的输出可以看出整个执行顺序如下:
1)执行BeanFactoryPostProcessor
2)执行BeanPostProcessor的postProcessBeforeInitialization方法。
4)执行init-method属性指定的方法
其中第2步就是spring容器加载了bean的定义文件,将其解析成BeanDefinition,可以参考我之前的博文Spring源码解读 IOC容器初始化,第4步就是执行BeanFactoryPostProcessor,第5步是向BeanFactory注入BeanPostProcessor,BeanPostProcessor方法是在getBean()触发的,如果不是延时初始化,在第11步就执行了,如果是在用户手工调用getBean()时触发。这也是为什么我在配置文件中将lazy-init设置成true的原因。 我们先看一下第4步的源码,我在调试的时候发现postProcessBeanFactory()是个空实现,在此不追究,主要看一下invokeBeanFactoryPostProcessors()方法
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); }
发现是通过PostProcessorRegistrationDelegate来执行的,我们在看一下PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors()方法:
public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { Set<String> processedBeans = new HashSet<String>(); if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>(); List<BeanDefinitionRegistryPostProcessor> registryPostProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>(); for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryPostProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; registryPostProcessor.postProcessBeanDefinitionRegistry(registry); registryPostProcessors.add(registryPostProcessor); } else { regularPostProcessors.add(postProcessor); } } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! // Separate between BeanDefinitionRegistryPostProcessors that implement // PriorityOrdered, Ordered, and the rest. //获取BeanFactoryPostProcessor String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>(); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } //根据优先级排序 OrderComparator.sort(priorityOrderedPostProcessors); registryPostProcessors.addAll(priorityOrderedPostProcessors); //按照排序顺序循环执行 invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry); // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>(); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } OrderComparator.sort(orderedPostProcessors); registryPostProcessors.addAll(orderedPostProcessors); invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry); // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear. boolean reiterate = true; while (reiterate) { reiterate = false; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName)) { BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class); registryPostProcessors.add(pp); processedBeans.add(ppName); pp.postProcessBeanDefinitionRegistry(registry); reiterate = true; } } } // Now, invoke the postProcessBeanFactory callback of all processors handled so far. invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { // Invoke factory processors registered with the context instance. invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, // Ordered, and the rest. List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>(); List<String> orderedPostProcessorNames = new ArrayList<String>(); List<String> nonOrderedPostProcessorNames = new ArrayList<String>(); for (String ppName : postProcessorNames) { if (processedBeans.contains(ppName)) { // skip - already processed in first phase above } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. OrderComparator.sort(priorityOrderedPostProcessors); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // Next, invoke the BeanFactoryPostProcessors that implement Ordered. List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>(); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } OrderComparator.sort(orderedPostProcessors); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>(); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); }
整个方法很长很长,其实主要就是三步,第一获取实现了BeanFactoryPostProcessor的类,第二根据优先级进行排序,第三根据排好的顺序循环执行。当然里面有Spring内置的BeanFactoryPostProcess,还有一些无需排序的BeanFactoryPostProcessor。
也是很长很长,其实就是获取BeanPostProcessor然后注入给BeanFactory,具体的执行通过getBean()触发,getBean()的具体过程就不分析了,可以参考我之前的博文,这里主要看一下getBean()的初始化过程。代码如下
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override //执行Aware方法 public Object run() { invokeAwareMethods(beanName, bean); return null; } }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { //执行BeanPostProcessor里的postProcessBeforeInitialization方法 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { //执行初始化方法 //先执行InitializingBean的afterPropertiesSet方法,再执行init-method属性指定的方法 invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { //执行BeanPostProcessor里的postProcessAftrerInitialization方法 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }在看一下invokeInitMethod()方法
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable { boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isDebugEnabled()) { logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { try { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { @Override public Object run() throws Exception { ((InitializingBean) bean).afterPropertiesSet(); return null; } }, getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { //执行实现了InitializingBean的afterPropertiesSet方法 ((InitializingBean) bean).afterPropertiesSet(); } } if (mbd != null) { String initMethodName = mbd.getInitMethodName(); if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { //执行init-method属性执定的方法 invokeCustomInitMethod(beanName, bean, mbd); }在这俩个方法中除了之前我们测试中实现的初始化方法,还有一个执行Aware的方法,再说一下官方文档中说Spring提供了一系列的Aware接口使得bean可以从容器获取需要的资源。个人觉得不适合来控制Bean的初始化。
至此整个分析结束。