上一篇Spring源碼十九:Bean實例化流程二中,我們主要討論了單例Bean創建對象的主要方法getSingleton了解到了他的核心流程無非是:通過一個簡單工廠的getObject方法來實例化bean,當然spring在實例化前后提供了擴展如:beforeSingletonCreation與afterSingletonCreate,同樣為了提供性能會將實例化后的單例bean放入緩存中;又因為spring設計之初存在三級緩存,所以在放入緩存的時候又會將其他兩次的緩存清除。
簡單的回憶了之前的內容,我們發現還有一個很重要的點我們沒有說到那就是怎么通過簡單工廠來創建實例對象的,這一篇咱們詳細討論一下:
createBean
/*** Central method of this class: creates a bean instance, 創建bean實例對象* populates the bean instance, applies post-processors, etc. 填充bean實例、應用后置處理器* @see #doCreateBean*/@Overrideprotected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {if (logger.isTraceEnabled()) {logger.trace("Creating instance of bean '" + beanName + "'");}RootBeanDefinition mbdToUse = mbd;// Make sure bean class is actually resolved at this point, and// clone the bean definition in case of a dynamically resolved Class// which cannot be stored in the shared merged bean definition.// 判斷需要創建的bean是否可以實例化、是否可以通過當前類加載器加載Class<?> resolvedClass = resolveBeanClass(mbd, beanName);if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {mbdToUse = new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}// Prepare method overrides.// 準備bean中的方法覆蓋try {mbdToUse.prepareMethodOverrides();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),beanName, "Validation of method overrides failed", ex);}try {// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.// 給BeanPostProcessors一個返回代理而不是目標bean實例的機會。Object bean = resolveBeforeInstantiation(beanName, mbdToUse);// 如果bean配置類后置處理器PostProcessor,則這里返回一個proxy代理對象if (bean != null) {return bean;}}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,"BeanPostProcessor before instantiation of bean failed", ex);}try {// bean實例對象創建方法Object beanInstance = doCreateBean(beanName, mbdToUse, args);if (logger.isTraceEnabled()) {logger.trace("Finished creating instance of bean '" + beanName + "'");}return beanInstance;}catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {// A previously detected exception with proper bean creation context already,// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.throw ex;}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);}}
因為lockup-method屬性與repliace-methon配置屬性,現在基本上沒有使用場景,而resolveBeanClass與preprareMethodOverrides是為了是實現這個兩個方法而生的,所以我們直接來看 resolveBeforeInstantiation方法。
resolveBeforeInstantiation
@Nullableprotected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {Object bean = null;if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {// Make sure bean class is actually resolved at this point.if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {Class<?> targetType = determineTargetType(beanName, mbd);if (targetType != null) {// BeanPostProcessor前置處理方法bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);if (bean != null) {// BeanPostProcessor后置處理方法bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);}}}mbd.beforeInstantiationResolved = (bean != null);}return bean;}protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);if (result != null) {return result;}}}return null;}public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;for (BeanPostProcessor processor : getBeanPostProcessors()) {Object current = processor.postProcessAfterInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;}
InstantiationAwareBeanPostProcessor
是 BeanPostProcessor
的一個子接口,提供了以下方法,用于在 Bean 實例化的不同階段進行干預:
postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
: 在 Bean 實例化之前調用。postProcessAfterInstantiation(Object bean, String beanName)
: 在 Bean 實例化之后調用。postProcessProperties(PropertyValues pvs, Object bean, String beanName)
: 在 Bean 的屬性設置之前調用。
這些方法提供了在 Bean 實例化過程中進行自定義邏輯處理的機會,可以用于 Bean 的替換、屬性的預處理等操作。
示例代碼:
public class CustomInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {if ("myBean".equals(beanName)) {System.out.println("Before instantiation of " + beanName);// 可以返回一個代理對象或自定義的 Bean 實例}return null; // 返回 null 表示繼續默認的實例化過程}@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) {System.out.println("After instantiation of " + beanName);return true; // 返回 true 表示繼續進行屬性設置}@Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {System.out.println("Processing properties for " + beanName);return pvs; // 可以修改屬性值}
}
InstantiationAwareBeanPostProcessor
擴展了 BeanPostProcessor
的功能,提供了在 Bean 實例化的不同階段進行干預的能力。通過實現 InstantiationAwareBeanPostProcessor
接口,開發人員可以在 Bean 實例化過程中插入自定義邏輯,實現更靈活的 Bean 管理和控制。
實例化與初始化
為了更好地理解 BeanPostProcessor
和 InstantiationAwareBeanPostProcessor
的區別,我們需要明確實例化和初始化的概念。
- 實例化:實例化是從零到一創建一個 Bean 的過程,即通過調用構造函數生成 Bean 的實例。
- 初始化:初始化是在 Bean 實例化之后進行的配置過程,包括屬性注入、調用初始化方法等。
在 Spring 容器中,Bean 的生命周期大致分為以下幾個階段:
- 實例化:通過調用構造函數創建 Bean 實例。
- 屬性注入:將依賴的屬性注入到 Bean 中。
- 初始化:調用自定義的初始化方法,進行額外的配置。
BeanPostProcessor 與 InstantiationAwareBeanPostProcessor 的區別
-
作用階段:
BeanPostProcessor
主要作用于初始化階段,即在 Bean 的屬性已經注入之后進行處理。InstantiationAwareBeanPostProcessor
作用于實例化階段和屬性注入階段,允許在 Bean 實例化之前、之后以及屬性注入之前進行處理。
-
用途:
BeanPostProcessor
常用于在 Bean 初始化之前和之后執行一些通用的處理邏輯,如代理增強、配置驗證等。InstantiationAwareBeanPostProcessor
常用于在 Bean 實例化過程中執行一些特殊的處理邏輯,如提前終止 Bean 創建、動態生成代理對象、修改屬性注入邏輯等。
這個方法是在 Bean 初始化后應用所有注冊的 BeanPostProcessor 的 postProcessAfterInitialization 方法,其設計和實現反映了 Spring 框架中依賴注入和面向切面編程的核心理念。
Spring Bean 生命周期管理
在 Spring 框架中,Bean 的生命周期經歷了多個階段,包括實例化、依賴注入、初始化和銷毀等。applyBeanPostProcessorsAfterInitialization
方法所處的階段是在 Bean 初始化之后,即在所有屬性被設置后,執行自定義的后處理邏輯。
BeanPostProcessor 接口作用
BeanPostProcessor 接口定義了在 Bean 初始化前后可以插入自定義邏輯的能力。Spring 容器在創建 Bean 的過程中,會檢查是否注冊了 BeanPostProcessor,如果有,則會在相應的階段調用其方法。其中,postProcessAfterInitialization 方法是在 Bean 初始化完成后被調用的,允許開發者對 Bean 進行額外的處理或修改。
applyBeanPostProcessorsAfterInitialization 方法分析
-
初始化結果對象:方法開始時,首先將
result
對象初始化為existingBean
,即當前的 Bean 實例。這個existingBean
是在容器中已經完成初始化的對象。 -
遍歷處理器列表:方法接著遍歷所有注冊的 BeanPostProcessor,對每一個后處理器調用其 postProcessAfterInitialization 方法。
- 每個處理器可以在方法內部執行任何與 Bean 相關的操作,例如添加代理、執行驗證、修改屬性等。
- 如果某個處理器返回
null
,則表示不需要進一步處理,直接返回當前的result
對象。
-
返回處理后的結果:最終返回經過所有后處理器處理后的
result
對象。這個對象可能是原始的existingBean
,也可能是經過多個處理器處理后的新對象。
技術原理分析
-
面向切面編程(AOP)的應用:通過 BeanPostProcessor 接口,Spring 實現了 AOP 的一種簡單形式。開發者可以在 Bean 初始化后插入切面邏輯,例如添加事務、日志等。
-
依賴注入的增強:允許在 Bean 初始化后對依賴關系進行增強或修改,以適應不同的運行時需求。
-
靈活性與可擴展性:applyBeanPostProcessorsAfterInitialization 方法展示了 Spring 框架在管理 Bean 生命周期時的高度靈活性和可擴展性。開發者可以通過注冊自定義的 BeanPostProcessor 實現特定的業務邏輯,而不必修改現有的 Bean 實現代碼。
applyBeanPostProcessorsAfterInitialization 方法在 Spring 框架中扮演了重要角色,通過它,開發者可以在 Bean 初始化完成后添加自定義邏輯,擴展和定制應用程序的行為。理解這個方法的工作原理和技術實現,有助于深入理解 Spring 容器的工作機制,提升對 Bean 生命周期管理的控制和應用開發的靈活性。