一、目標
如果你在自己的實際工作中開發過基于 Spring 的技術組件,或者學習過關于SpringBoot 中間件設計和開發等內容。那么你一定會繼承或者實現了 Spring對外暴露的類或接口,在接口的實現中獲取了 BeanFactory 以及 Bean 對象的獲取等內容,并對這些內容做一些操作,例如:修改 Bean 的信息,添加日志打印、處理數據庫路由對數據源的切換、給 RPC 服務連接注冊中心等。在對容器中 Bean 的實例化過程添加擴展機制的同時,還需要把目前關于Spring.xml 初始化和加載策略進行優化,因為我們不太可能讓面向 Spring 本身開發的 DefaultListableBeanFactory 服務,直接給予用戶使用。修改點如下:
DefaultListableBeanFactory、XmlBeanDefinitionReader,是我們在目前 Spring 框架中對于服務功能測試的使用方式,它能很好的體現出 Spring 是如何對 xml 加載以及注冊Bean 對象的操作過程,但這種方式是面向 Spring 本身的,還不具備一定的擴展性。 就像我們現在需要提供出一個可以在 Bean 初始化過程中,完成對 Bean 對象的擴展時,就很難做到自動化處理。所以我們要把 Bean 對象擴展機制功能和對Spring 框架上下文的包裝融合起來,對外提供完整的服務。
二、設計
為了能滿足于在 Bean 對象從注冊到實例化的過程中執行用戶的自定義操作,就需要在 Bean 的定義和初始化過程中插入接口類,這個接口再有外部去實現自己需要的服務。那么在結合對 Spring 框架上下文的處理能力,就可以滿足我們的目標需求了。整體設計結構如下圖:
滿足于對 Bean 對象擴展的兩個接口,其實也是 Spring 框架中非常具有重量級的兩個接口:BeanFactoryPostProcess 和 BeanPostProcessor,也幾乎是大家在使用 Spring框架額外新增開發自己組建需求的兩個必備接口。 BeanFactoryPostProcessor,是由Spring框架組建提供的容器擴展機制,允許在 Bean 對象注冊后但未實例化之前,對 Bean 的定義信息 BeanDefinition 執行修改操作。 BeanPostProcessor,也是 Spring 提供的擴展機制,不過 BeanPostProcessor 是在Bean 對象實例化之后修改 Bean 對象,也可以替換 Bean 對象。這部分與后面要實現的 AOP 有著密切的關系。 同時如果只是添加這兩個接口,不做任何包裝,那么對于使用者來說還是非常麻煩的。我們希望于開發 Spring 的上下文操作類,把相應的 XML加載 、注冊、實 例化以及新增的修改和擴展都融合進去,讓 Spring 可以自動掃描到我們的新增服務,便于用戶使用。
三、實現
工程結構
在整個類圖中主要體現出來的是關于 Spring 應用上下文以及對 Bean 對象擴展機制的實現。 以繼承了 ListableBeanFactory 接口的 ApplicationContext 接口開始,擴展出一系列應用上下文的抽象實現類,并最終完成ClassPathXmlApplicationContext 類的實現。而這個類就是最后交給用戶使用的類。 同時在實現應用上下文的過程中,通過定義接口:BeanFactoryPostProcessor、BeanPostProcessor 兩個接口,把關于對 Bean 的擴展機制串聯進去了。
BeanFactoryPostProcessor:是由 Spring 框架組建提供的容器擴展機制,允許在Bean 對象注冊后但未實例化之前,對 Bean 的定義信息 BeanDefinition 執行修改操作。在spring源碼中,針對的是BeanFactory的擴展,可以在容器啟動時修改bean的定義。
public interface BeanFactoryPostProcessor { void postProcessBeanFactory ( ConfigurableListableBeanFactory beanFactory
) throws BeansException ;
}
在 Spring 源碼中有這樣一段描述 Allows for custom modification of an application context’s bean definitions,adapting the bean property values of the context’s underlying bean factory. 其實也就是說這個接口是滿足于在所有的 BeanDefinition 加載完成 后,實例化 Bean 對象之前,提供修改 BeanDefinition 屬性的機制。
BeanPostProcessor:,也是 Spring 提供的擴展機制,不過 BeanPostProcessor 是在Bean 對象實例化之后修改 Bean 對象,也可以替換 Bean 對象(AOP)。在spring源碼中屬于bean級別的處理,針對某個具體的bean進行處理接口提供了兩個方法,分別是初始化前和初始化后執行方法,具體這個初始化方法指的是什么方法,類似我們在定義bean時,定義了init-method所指定的方法這兩個方法分別在init方法前后執行,需要注意一點,我們定義一個類實現了BeanPostProcessor,默認是會對整個Spring容器中所有的bean進行處理。
public interface BeanPostProcessor { Object postProcessBeforeInitialization ( Object bean
, String beanName
) throws BeansException ; Object postProcessAfterInitialization ( Object bean
, String beanName
) throws BeansException ;
}
在 Spring 源碼中有這樣一段描述 Factory hook that allows for custom modification of new bean instances,e.g. checking for marker interfaces or wrapping them with proxies. 也就是提供了修改新實例化 Bean 對象的擴展點。 另外此接口提供了兩個方法: postProcessBeforeInitialization 用于在Bean 對象執行初始化方法之前,執行此方法、 postProcessAfterInitialization 用于在 Bean 對象執行初始化方法之后,執行此方法。
定義上下文接口
public interface ApplicationContext extends ListableBeanFactory {
}
context 是本次實現應用上下文功能新增的服務包 ApplicationContext ,繼承于 ListableBeanFactory ,也就繼承了關于 BeanFactory方法,比如一些 getBean 的方法。另外 ApplicationContext 本身是 Central 接口,但目前還不需要添加一些獲取 ID 和父類上下文,所以暫時沒有接口方法的定義。
public interface ConfigurableApplicationContext extends ApplicationContext { void refresh ( ) throws BeansException ; void registerShutdownHook ( ) ; void close ( ) ;
}
ConfigurableApplicationContext 繼承自 ApplicationContext ,并提供了 refresh 這個核心方法。 如果你有看過一些 Spring 源碼,那么一定會看到這個方法。 接下 來也是需要在上下文的實現中完成刷新容器的操作過程
應用上下文抽象類實現
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext { @Override public void refresh ( ) throws BeansException { refreshBeanFactory ( ) ; ConfigurableListableBeanFactory beanFactory
= getBeanFactory ( ) ; invokeBeanFactoryPostProcessors ( beanFactory
) ; registerBeanPostProcessors ( beanFactory
) ; beanFactory
. preInstantiateSingletons ( ) ; } protected abstract void refreshBeanFactory ( ) throws BeansException ; protected abstract ConfigurableListableBeanFactory getBeanFactory ( ) ; private void invokeBeanFactoryPostProcessors ( ConfigurableListableBeanFactory beanFactory
) { Map < String , BeanFactoryPostProcessor > beanFactoryPostProcessorMap
= beanFactory
. getBeansOfType ( BeanFactoryPostProcessor . class ) ; for ( BeanFactoryPostProcessor beanFactoryPostProcessor
: beanFactoryPostProcessorMap
. values ( ) ) { beanFactoryPostProcessor
. postProcessBeanFactory ( beanFactory
) ; } } private void registerBeanPostProcessors ( ConfigurableListableBeanFactory beanFactory
) { Map < String , BeanPostProcessor > beanPostProcessorMap
= beanFactory
. getBeansOfType ( BeanPostProcessor . class ) ; for ( BeanPostProcessor beanPostProcessor
: beanPostProcessorMap
. values ( ) ) { beanFactory
. addBeanPostProcessor ( beanPostProcessor
) ; } } @Override public < T > Map < String , T > getBeansOfType ( Class < T > type
) throws BeansException { return getBeanFactory ( ) . getBeansOfType ( type
) ; } @Override public String [ ] getBeanDefinitionNames ( ) { return getBeanFactory ( ) . getBeanDefinitionNames ( ) ; } @Override public Object getBean ( String name
) throws BeansException { return getBeanFactory ( ) . getBean ( name
) ; } @Override public Object getBean ( String name
, Object . . . args
) throws BeansException { return getBeanFactory ( ) . getBean ( name
, args
) ; } @Override public < T > T getBean ( String name
, Class < T > requiredType
) throws BeansException { return getBeanFactory ( ) . getBean ( name
, requiredType
) ; } @Override public void registerShutdownHook ( ) { Runtime . getRuntime ( ) . addShutdownHook ( new Thread ( this :: close ) ) ; } @Override public void close ( ) { getBeanFactory ( ) . destroySingletons ( ) ; }
}
AbstractApplicationContext 繼承 DefaultResourceLoader 是為了處理spring.xml 配置資源的加載。 之后是在 refresh() 定義實現過程,包括: 創建 BeanFactory ,并加載 BeanDefinition 獲取 BeanFactory 在 Bean 實例化之前,執行 BeanFactoryPostProcessor (Invoke factory processors registered as beans in the context.) BeanPostProcessor 需要提前于其他 Bean 對象實例化之前執行注冊操作 提前實例化單例 Bean 對象 另外把定義出來的抽象方法, refreshBeanFactory() 、 getBeanFactory() 由后面的繼承此抽象類的其他抽象類實現。
獲取 Bean 工廠和加載資源
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext { private DefaultListableBeanFactory beanFactory
; @Override protected void refreshBeanFactory ( ) throws BeansException { DefaultListableBeanFactory beanFactory
= createBeanFactory ( ) ; loadBeanDefinitions ( beanFactory
) ; this . beanFactory
= beanFactory
; } private DefaultListableBeanFactory createBeanFactory ( ) { return new DefaultListableBeanFactory ( ) ; } protected abstract void loadBeanDefinitions ( DefaultListableBeanFactory beanFactory
) ; @Override protected ConfigurableListableBeanFactory getBeanFactory ( ) { return beanFactory
; }
}
在 refreshBeanFactory() 中主要是獲取了 DefaultListableBeanFactory的實例化以及對資源配置的加載操作loadBeanDefinitions(beanFactory) beanFactory),在加載完成后即可完成對spring.xml 配置文件中 Bean 對象的定義和注冊,同時也包括實現了接口BeanFactoryPostProcessor 、 BeanPostProcessor的配置 Bean 信息。 但此時資源加載還只是定義了一個抽象類方法loadBeanDefinitions(DefaultListableBeanFactory beanFactory)beanFactory),繼續由其他抽象類繼承實現。
上下文中對配置信息的加載
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableApplicationContext { @Override protected void loadBeanDefinitions ( DefaultListableBeanFactory beanFactory
) { XmlBeanDefinitionReader beanDefinitionReader
= new XmlBeanDefinitionReader ( beanFactory
, this ) ; String [ ] configLocations
= getConfigLocations ( ) ; if ( null != configLocations
) { beanDefinitionReader
. loadBeanDefinitions ( configLocations
) ; } } protected abstract String [ ] getConfigLocations ( ) ;
}
在 AbstractXmlApplicationContext 抽象類的 loadBeanDefinitions 方法實現中,使用 XmlBeanDefinitionReader 類,處理了關于 XML 文件配置信息的操作。 同時這里又留下了一個抽象類方法getConfigLocations()getConfigLocations(),此方法是為了從入口上下文類,拿到配置信息的地址描述。
應用上下文實現類 (ClassPathXmlApplicationContext)
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext { private String [ ] configLocations
; public ClassPathXmlApplicationContext ( ) { } public ClassPathXmlApplicationContext ( String configLocations
) throws BeansException { this ( new String [ ] { configLocations
} ) ; } public ClassPathXmlApplicationContext ( String [ ] configLocations
) throws BeansException { this . configLocations
= configLocations
; refresh ( ) ; } @Override protected String [ ] getConfigLocations ( ) { return configLocations
; }
}
ClassPathXmlApplicationContext ,是具體對外給用戶提供的應用上下文方法。 在繼承了 AbstractXmlApplicationContext 以及層層抽象類 的功能分離實現后,在此類 ClassPathXmlApplicationContext 的實現中就簡單多了,主要是對繼承抽象類中方法的調用和提供了配置文件地址信息。
在 Bean 創建時完成前置和后置處理
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory { private InstantiationStrategy instantiationStrategy
= new CglibSubclassingInstantiationStrategy ( ) ; @Override protected Object createBean ( String beanName
, BeanDefinition beanDefinition
, Object [ ] args
) throws BeansException { Object bean
= null ; try { bean
= createBeanInstance ( beanDefinition
, beanName
, args
) ; applyPropertyValues ( beanName
, bean
, beanDefinition
) ; bean
= initializeBean ( beanName
, bean
, beanDefinition
) ; } catch ( Exception e
) { throw new BeansException ( "Instantiation of bean failed" , e
) ; } registerDisposableBeanIfNecessary ( beanName
, bean
, beanDefinition
) ; addSingleton ( beanName
, bean
) ; return bean
; } protected void registerDisposableBeanIfNecessary ( String beanName
, Object bean
, BeanDefinition beanDefinition
) { if ( bean
instanceof DisposableBean || StrUtil . isNotEmpty ( beanDefinition
. getDestroyMethodName ( ) ) ) { registerDisposableBean ( beanName
, new DisposableBeanAdapter ( bean
, beanName
, beanDefinition
) ) ; } } protected Object createBeanInstance ( BeanDefinition beanDefinition
, String beanName
, Object [ ] args
) { Constructor constructorToUse
= null ; Class < ? > beanClass
= beanDefinition
. getBeanClass ( ) ; Constructor < ? > [ ] declaredConstructors
= beanClass
. getDeclaredConstructors ( ) ; for ( Constructor ctor
: declaredConstructors
) { if ( null != args
&& ctor
. getParameterTypes ( ) . length
== args
. length
) { constructorToUse
= ctor
; break ; } } return getInstantiationStrategy ( ) . instantiate ( beanDefinition
, beanName
, constructorToUse
, args
) ; } protected void applyPropertyValues ( String beanName
, Object bean
, BeanDefinition beanDefinition
) { try { PropertyValues propertyValues
= beanDefinition
. getPropertyValues ( ) ; for ( PropertyValue propertyValue
: propertyValues
. getPropertyValues ( ) ) { String name
= propertyValue
. getName ( ) ; Object value
= propertyValue
. getValue ( ) ; if ( value
instanceof BeanReference ) { BeanReference beanReference
= ( BeanReference ) value
; value
= getBean ( beanReference
. getBeanName ( ) ) ; } BeanUtil . setFieldValue ( bean
, name
, value
) ; } } catch ( Exception e
) { throw new BeansException ( "Error setting property values:" + beanName
) ; } } public InstantiationStrategy getInstantiationStrategy ( ) { return instantiationStrategy
; } public void setInstantiationStrategy ( InstantiationStrategy instantiationStrategy
) { this . instantiationStrategy
= instantiationStrategy
; } private Object initializeBean ( String beanName
, Object bean
, BeanDefinition beanDefinition
) { Object wrappedBean
= applyBeanPostProcessorsBeforeInitialization ( bean
, beanName
) ; try { invokeInitMethods ( beanName
, wrappedBean
, beanDefinition
) ; } catch ( Exception e
) { throw new BeansException ( "Invocation of init method of bean[" + beanName
+ "] failed" , e
) ; } wrappedBean
= applyBeanPostProcessorsAfterInitialization ( bean
, beanName
) ; return wrappedBean
; } private void invokeInitMethods ( String beanName
, Object bean
, BeanDefinition beanDefinition
) throws Exception { if ( bean
instanceof InitializingBean ) { ( ( InitializingBean ) bean
) . afterPropertiesSet ( ) ; } String initMethodName
= beanDefinition
. getInitMethodName ( ) ; if ( StrUtil . isNotEmpty ( initMethodName
) ) { Method initMethod
= beanDefinition
. getBeanClass ( ) . getMethod ( initMethodName
) ; if ( null == initMethod
) { throw new BeansException ( "Could not find an init method named '" + initMethodName
+ "' on bean with name '" + beanName
+ "'" ) ; } initMethod
. invoke ( bean
) ; } } @Override public Object applyBeanPostProcessorsBeforeInitialization ( Object existingBean
, String beanName
) throws BeansException { Object result
= existingBean
; for ( BeanPostProcessor processor
: getBeanPostProcessors ( ) ) { Object current
= processor
. postProcessBeforeInitialization ( result
, beanName
) ; if ( null == current
) return result
; result
= current
; } return result
; } @Override public Object applyBeanPostProcessorsAfterInitialization ( Object existingBean
, String beanName
) throws BeansException { Object result
= existingBean
; for ( BeanPostProcessor processor
: getBeanPostProcessors ( ) ) { Object current
= processor
. postProcessAfterInitialization ( result
, beanName
) ; if ( null == current
) return result
; result
= current
; } return result
; }
}
實現 BeanPostProcessor 接口后,會涉及到兩個接口方法,postProcessBeforeInitialization 、postProcessAfterInitialization ,分別作用于 Bean 對象執行初始化前后的額外處理。 也就是需要在創建 Bean 對象時,在 createBean 方法中添加initializeBean(beanName, bean, beanDefinition); 操作。而這個操作主要主要是對于方法applyBeanPostProcessorsBeforeInitialization 、applyBeanPostProces sorsAfterInitialization 的使用。 另外需要提一下,applyBeanPostProcessorsBeforeInitialization 、applyBeanPostProcessorsAfterInitialization 兩個方法是在接口類 AutowireCapableBeanFactory 中新增加的。
四、測試
事先準備
public class UserDao { private static Map < String , String > hashMap
= new HashMap < > ( ) ; public void initDataMethod ( ) { System . out
. println ( "執行:init-method" ) ; hashMap
. put ( "10001" , "小傅哥" ) ; hashMap
. put ( "10002" , "八杯水" ) ; hashMap
. put ( "10003" , "阿毛" ) ; } public void destroyDataMethod ( ) { System . out
. println ( "執行:destroy-method" ) ; hashMap
. clear ( ) ; } public String queryUserName ( String uId
) { return hashMap
. get ( uId
) ; }
}
public class UserService implements InitializingBean , DisposableBean { private String uId
; private String company
; private String location
; private UserDao userDao
; @Override public void destroy ( ) throws Exception { System . out
. println ( "執行:UserService.destroy" ) ; } @Override public void afterPropertiesSet ( ) throws Exception { System . out
. println ( "執行:UserService.afterPropertiesSet" ) ; } public String queryUserInfo ( ) { return userDao
. queryUserName ( uId
) + "," + company
+ "," + location
; } public String getuId ( ) { return uId
; } public void setuId ( String uId
) { this . uId
= uId
; } public String getCompany ( ) { return company
; } public void setCompany ( String company
) { this . company
= company
; } public String getLocation ( ) { return location
; } public void setLocation ( String location
) { this . location
= location
; } public UserDao getUserDao ( ) { return userDao
; } public void setUserDao ( UserDao userDao
) { this . userDao
= userDao
; }
}
Dao 、 Service ,是我們平常開發經常使用的場景。在 UserService 中注入UserDao ,這樣就能體現出 Bean 屬性的依賴了。 另外這里新增加了 company 、 location ,兩個屬性信息,便于測試BeanPostProcessor 、 BeanFactoryPostProcessor 兩個接口對 Bean 屬性信息擴展的作用。
實現 BeanPostProcessor 和 BeanFactoryPostProcessor
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory ( ConfigurableListableBeanFactory beanFactory
) throws BeansException { BeanDefinition beanDefinition
= beanFactory
. getBeanDefinition ( "userService" ) ; PropertyValues propertyValues
= beanDefinition
. getPropertyValues ( ) ; propertyValues
. addPropertyValue ( new PropertyValue ( "company" , "改為:字節跳動" ) ) ; }
}
public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization ( Object bean
, String beanName
) throws BeansException { if ( "userService" . equals ( beanName
) ) { UserService userService
= ( UserService ) bean
; userService
. setLocation ( "改為:北京" ) ; } return bean
; } @Override public Object postProcessAfterInitialization ( Object bean
, String beanName
) throws BeansException { return bean
; }
}
如果你在 Spring 中做過一些組件的開發那么一定非常熟悉這兩個類,本文的測試也是實現了這兩個類,對實例化過程中的 Bean 對象做一些操作。
配置文件
基礎配置,無BeanFactoryPostProcessor、BeanPostProcessor,實現類
<?xml version="1.0" encoding="UTF-8"?> < beans> < bean id = " userDao" class = " cn.bugstack.springframework.test.bean.UserDao" /> < bean id = " userService" class = " cn.bugstack.springframework.test.bean.UserService" > < property name = " uId" value = " 10001" /> < property name = " company" value = " 騰訊" /> < property name = " location" value = " 深圳" /> < property name = " userDao" ref = " userDao" /> </ bean> </ beans>
增強配置,有BeanFactoryPostProcessor、BeanPostProcessor,實現類
<?xml version="1.0" encoding="UTF-8"?>
< beans>
< bean id = " userDao" class = " cn.bugstack.springframework.test.bean.UserDao" />
< bean id = " userService" class = " cn.bugstack.springframework.test.bean.UserService" >
< property name = " uId" value = " 10001" />
property name="company" value="騰訊"/>
< property name = " location" value = " 深圳" />
< property name = " userDao" ref = " userDao" />
</ bean>
< bean class = " cn.bugstack.springframework.test.common.MyBeanPostProcessor" />
< bean class = " cn.bugstack.springframework.test.common.MyBeanFactoryPostProcessor" />
</ beans>
這里提供了兩個配置文件,一個是不包含 BeanFactoryPostProcessor 、BeanPostProcessor ,另外一個是包含的。之所以這樣配置主要對照驗證,在運用Spring 新增加的應用上下文和不使用的時候,都是怎么操作的。
不用應用上下文
@Test public void test_BeanFactoryPostProcessorAndBeanPostProcessor ( ) { DefaultListableBeanFactory beanFactory
= new DefaultListableBeanFactory ( ) ; XmlBeanDefinitionReader reader
= new XmlBeanDefinitionReader ( beanFactory
) ; reader
. loadBeanDefinitions ( "classpath:spring.xml" ) ; MyBeanFactoryPostProcessor beanFactoryPostProcessor
= new MyBeanFactoryPostProcessor ( ) ; beanFactoryPostProcessor
. postProcessBeanFactory ( beanFactory
) ; MyBeanPostProcessor beanPostProcessor
= new MyBeanPostProcessor ( ) ; beanFactory
. addBeanPostProcessor ( beanPostProcessor
) ; UserService userService
= beanFactory
. getBean ( "userService" , UserService . class ) ; String result
= userService
. queryUserInfo ( ) ; System . out
. println ( "測試結果:" + result
) ; }
DefaultListableBeanFactory 創建 beanFactory 并使用 XmlBeanDefinitionReader加載配置文件的方式,還是比較熟悉的。 接下來就是對 MyBeanFactoryPostProcessor 和 MyBeanPostProcessor 的處理,一個是在 BeanDefinition 加載完成 & Bean 實例化之前,修改 BeanDefinition 的屬性值,另外一個是在 Bean 實例化之后,修改 Bean 屬性信息。
使用應用上下文
@Test public void test_xml ( ) { ClassPathXmlApplicationContext applicationContext
= new ClassPathXmlApplicationContext ( "classpath:springPostProcessor.xml" ) ; UserService userService
= applicationContext
. getBean ( "userService" , UserService . class ) ; String result
= userService
. queryUserInfo ( ) ; System . out
. println ( "測試結果:" + result
) ; }
使用新增加的 ClassPathXmlApplicationContext 應用上下文類,再操作起來就方便多了, 這才是面向用戶使用的類 ,在這里可以一步把配置文件交給ClassPathXmlApplicationContext ,也不需要管理一些自定義實現的 Spring 接口的類。
上面兩個的測試結果是一樣的,不過使用應用上下文的方式明顯更加方便
五、總結
本文主要新增了 Spring 框架中兩個非常重要的接口 BeanFactoryPostProcess 、BeanPostProcessor 同時還添加了關于應用上下文的實現, ApplicationContext 接口的定義是繼承 BeanFactory 外新增加功能的接口,它可以滿足于自動識別、資源加載、容器事件、監聽器等功能,同時例如一些國際化支持、單例 Bean 自動初始化等,也是可以在這個類里實現和擴充的。 通過本文的實現一定會非常了解 BeanFactoryPostProcess 、 BeanPostProcessor ,以后再做一些關于 Spring 中間件的開發時,如果需要用到 Bean 對象的獲取以及修改一些屬性信息,那么就可以使用這兩個接口了。同時 BeanPostProcessor 也是實現 AOP 切面技術的關鍵所在。
總結
以上是生活随笔 為你收集整理的手写简版spring --6--应用上下文(BeanPostProcessor 和 BeanFactoryPostProcessor) 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。