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對象而返回一個代理對象,這也就給各類操做提供了可能性。具體之後再詳細地分析吧。