Spring IOC容器 源码解析系列,建议你们按顺序阅读,欢迎讨论spring
(spring源码均为4.1.6.RELEASE版本)编程
在IOC容器(三)-GetBean中的AbstractBeanFactory的doCreateBean方法中,曾主要分析过三个方法app
这三个方法是按顺序执行的,显示实例化bean,再对bean的属性和依赖的注入,最后进行bean的初始化。bean的初始化就是bean对象被使用以前所要作的准备工做,在spring容器中主要作了下面几件事:post
上面的各个操做都是按顺序来进行的。为何单独花一章来讨论bean的初始化,由于涉及了几个经常使用的初始化方法,而它们的做用点从外部来看都是同样的,但实际的执行是有前后之分的。spa
init-method是在Spring的xml配置文件中经过bean标签的init-method属性来配置的。例如:.net
<bean id="sampleBean" class="com.lntea.spring.demo.bean.SampleBean" init-method="prepare"></bean>
即在bean的初始化时执行prepare方法代理
InitializingBean是spring提供的编程方式的bean初始化接口code
public interface InitializingBean { void afterPropertiesSet() throws Exception; }
实现afterPropertiesSet方法就会在spring初始化bean时执行xml
BeanPostProcessor是Spring重要的扩展方式之一,在bean的各个时期如实例化,配置,初始化等定义了回调方法进行扩展。这里只讨论默认的两个方法,用来在bean初始化的先后执行回调。对象
public interface BeanPostProcessor { // 初始化前回调方法 Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; // 初始化后回调方法 Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; }
再来强调下初始化过程当中执行的顺序:
BeanPostProcessor的初始化前置回调方法 -> InitializingBean接口的初始化方法 -> init-method初始化方法 -> BeanPostProcessor的初始化后置回调方法
从源码上再来看下
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { // 初始化前置回调方法 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { // 初始化方法 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()) { // 初始化后置回调方法 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; } protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable { boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { // 先执行InitializingBean的初始化 ((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); } } }
BeanPostProcessor自己只定义了两个回调方法,在初始化的先后执行,但继承它的子接口对bean实例化的各个节点都加入了扩展点,从而容许对bean的建立过程自定义各类操做。Spring的文档中这样提到:
If you want to implement some custom logic after the Spring container finishes instantiating, configuring, and initializing a bean, you can plug in one or more BeanPostProcessor implementations.
若是你Spring容器完成实例化,配置和初始化bean以后实现一些自定义的逻辑,能够插入一个或多个的BeanPostProcessor实现。
若是你深刻去读Spring源码时,会发现BeanPostProcessor的扩展点甚至能够直接替代原有的bean对象而返回一个代理对象,这也就给各类操做提供了可能性。具体之后再详细地分析吧。