日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

手写简版spring --6--应用上下文(BeanPostProcessor 和 BeanFactoryPostProcessor)

發布時間:2025/3/15 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 手写简版spring --6--应用上下文(BeanPostProcessor 和 BeanFactoryPostProcessor) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、目標

如果你在自己的實際工作中開發過基于 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的定義。
  • //允許自定義修改 BeanDefinition 屬性信息 public interface BeanFactoryPostProcessor {/*** 在所有的 BeanDefinition 加載完成后,實例化 Bean 對象之前,提供修改 BeanDefinition 屬性的機制* @param beanFactory* @throws BeansException*/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 {/*** 在 Bean 對象執行初始化方法之前,執行此方法** @param bean* @param beanName* @return* @throws BeansException*/Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;/*** 在 Bean 對象執行初始化方法之后,執行此方法** @param bean* @param beanName* @return* @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 {/*** 刷新容器* @throws BeansException*/void refresh() throws BeansException;void registerShutdownHook();void close(); }

    ConfigurableApplicationContext 繼承自 ApplicationContext ,并提供了 refresh 這個核心方法。 如果你有看過一些 Spring 源碼,那么一定會看到這個方法。 接下 來也是需要在上下文的實現中完成刷新容器的操作過程

  • 應用上下文抽象類實現
  • public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {@Overridepublic void refresh() throws BeansException {// 1. 創建 BeanFactory,并加載 BeanDefinitionrefreshBeanFactory();// 2. 獲取 BeanFactoryConfigurableListableBeanFactory beanFactory = getBeanFactory();// 3. 在 Bean 實例化之前,執行 BeanFactoryPostProcessor (Invoke factory processors registered as beans in the context.)invokeBeanFactoryPostProcessors(beanFactory);// 4. BeanPostProcessor 需要提前于其他 Bean 對象實例化之前執行注冊操作registerBeanPostProcessors(beanFactory);// 5. 提前實例化單例Bean對象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);}}@Overridepublic <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {return getBeanFactory().getBeansOfType(type);}@Overridepublic String[] getBeanDefinitionNames() {return getBeanFactory().getBeanDefinitionNames();}@Overridepublic Object getBean(String name) throws BeansException {return getBeanFactory().getBean(name);}@Overridepublic Object getBean(String name, Object... args) throws BeansException {return getBeanFactory().getBean(name, args);}@Overridepublic <T> T getBean(String name, Class<T> requiredType) throws BeansException {return getBeanFactory().getBean(name, requiredType);}@Overridepublic void registerShutdownHook() {Runtime.getRuntime().addShutdownHook(new Thread(this::close));}@Overridepublic 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;@Overrideprotected void refreshBeanFactory() throws BeansException {DefaultListableBeanFactory beanFactory = createBeanFactory();loadBeanDefinitions(beanFactory);this.beanFactory = beanFactory;}private DefaultListableBeanFactory createBeanFactory() {return new DefaultListableBeanFactory();}protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory);@Overrideprotected 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 {@Overrideprotected 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() {}/*** 從 XML 中加載 BeanDefinition,并刷新上下文* @param configLocations* @throws BeansException*/public ClassPathXmlApplicationContext(String configLocations) throws BeansException {this(new String[]{configLocations});}/*** 從 XML 中加載 BeanDefinition,并刷新上下文* @param configLocations* @throws BeansException*/public ClassPathXmlApplicationContext(String[] configLocations) throws BeansException {this.configLocations = configLocations;refresh();}@Overrideprotected String[] getConfigLocations() {return configLocations;} }
  • ClassPathXmlApplicationContext ,是具體對外給用戶提供的應用上下文方法。
  • 在繼承了 AbstractXmlApplicationContext 以及層層抽象類 的功能分離實現后,在此類 ClassPathXmlApplicationContext 的實現中就簡單多了,主要是對繼承抽象類中方法的調用和提供了配置文件地址信息。
  • 在 Bean 創建時完成前置和后置處理
  • public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();@Overrideprotected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException {Object bean = null;try {bean = createBeanInstance(beanDefinition, beanName, args);// 給 Bean 填充屬性applyPropertyValues(beanName, bean, beanDefinition);// 執行 Bean 的初始化方法和 BeanPostProcessor 的前置和后置處理方法bean = initializeBean(beanName, bean, beanDefinition);} catch (Exception e) {throw new BeansException("Instantiation of bean failed", e);}// 注冊實現了 DisposableBean 接口的 Bean 對象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);}/*** Bean 屬性填充*/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) {// A 依賴 B,獲取 B 的實例化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) {// 1. 執行 BeanPostProcessor Before 處理Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);// 執行 Bean 對象的初始化方法try {invokeInitMethods(beanName, wrappedBean, beanDefinition);} catch (Exception e) {throw new BeansException("Invocation of init method of bean[" + beanName + "] failed", e);}// 2. 執行 BeanPostProcessor After 處理wrappedBean = applyBeanPostProcessorsAfterInitialization(bean, beanName);return wrappedBean;}private void invokeInitMethods(String beanName, Object bean, BeanDefinition beanDefinition) throws Exception {// 1. 實現接口 InitializingBeanif (bean instanceof InitializingBean) {((InitializingBean) bean).afterPropertiesSet();}// 2. 注解配置 init-method {判斷是為了避免二次執行銷毀}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);}}@Overridepublic 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;}@Overridepublic 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;@Overridepublic void destroy() throws Exception {System.out.println("執行:UserService.destroy");}@Overridepublic 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
  • //注冊后實例化前對beandefinifion修改 public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");PropertyValues propertyValues = beanDefinition.getPropertyValues();propertyValues.addPropertyValue(new PropertyValue("company", "改為:字節跳動"));} } //實例化后對userService進行修改 public class MyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if ("userService".equals(beanName)) {UserService userService = (UserService) bean;userService.setLocation("改為:北京");}return bean;}@Overridepublic 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 新增加的應用上下文和不使用的時候,都是怎么操作的。
  • 不用應用上下文
  • @Testpublic void test_BeanFactoryPostProcessorAndBeanPostProcessor(){// 1.初始化 BeanFactoryDefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();// 2. 讀取配置文件&注冊BeanXmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);reader.loadBeanDefinitions("classpath:spring.xml");// 3. BeanDefinition 加載完成 & Bean實例化之前,修改 BeanDefinition 的屬性值MyBeanFactoryPostProcessor beanFactoryPostProcessor = new MyBeanFactoryPostProcessor();beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);// 4. Bean實例化之后,修改 Bean 屬性信息MyBeanPostProcessor beanPostProcessor = new MyBeanPostProcessor();beanFactory.addBeanPostProcessor(beanPostProcessor);// 5. 獲取Bean對象調用方法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 屬性信息。
  • 使用應用上下文
  • @Testpublic void test_xml() {// 1.初始化 BeanFactoryClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:springPostProcessor.xml");// 2. 獲取Bean對象調用方法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)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。