日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Spring ioc容器與Bean的生命周期。

作者:帆 更新時間: 2024-07-18 編程語言

ApplicationContext 了,ApplicationContext 繼承自 BeanFactory,但是它不應該被理解為 BeanFactory 的實現類,而是說其內部持有一個實例化的 BeanFactory(DefaultListableBeanFactory)。以后所有的 BeanFactory 相關的操作其實是委托給這個實例來處理的。

public static void main(String[] args) {
? ? ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationfile.xml");
}

最基本啟動一個Spring容器的例子

  1. ApplicationContext: 這是Spring Framework中的一個核心接口,它代表了Spring IoC容器,并負責實例化、配置和管理應用程序中的對象。ApplicationContext可以加載配置文件、管理Bean之間的依賴關系,并提供了訪問Bean的機制。

2.ClassPathXmlApplicationContext: 是ApplicationContext接口的實現類之一,用于從類路徑中加載XML配置文件。它會在類路徑中搜索指定的配置文件,并根據配置文件中的定義來實例化和配置Bean。

public class App {
? ? public static void main(String[] args) {
? ? ? ? // 用我們的配置文件來啟動一個 ApplicationContext
? ? ? ? ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");

? ? ? ? System.out.println("context 啟動成功");

? ? ? ? // 從 context 中取出我們的 Bean,而不是用 new MessageServiceImpl() 這種方式
? ? ? ? MessageService messageService = context.getBean(MessageService.class);
? ? ? ? // 這句將輸出: hello world
? ? ? ? System.out.println(messageService.getMessage());
? ? }
}

  1. ApplicationContext 繼承了 ListableBeanFactory,這個 Listable 的意思就是,通過這個接口,我們可以獲取多個 Bean,大家看源碼會發現,最頂層 BeanFactory 接口的方法都是獲取單個 Bean 的。

  2. ApplicationContext 繼承了 HierarchicalBeanFactory,Hierarchical 單詞本身已經能說明問題了,也就是說我們可以在應用中起多個 BeanFactory,然后可以將各個 BeanFactory 設置為父子關系。

  3. AutowireCapableBeanFactory 這個名字中的 Autowire 大家都非常熟悉,它就是用來自動裝配 Bean 用的,但是仔細看上圖,ApplicationContext 并沒有繼承它,不過不用擔心,不使用繼承,不代表不可以使用組合,如果你看到 ApplicationContext 接口定義中的最后一個方法 getAutowireCapableBeanFactory() 就知道了

啟動過程分析

1.第一步,我們肯定要從 ClassPathXmlApplicationContext 的構造方法說起

2.接下來,就是 refresh(),這里簡單說下為什么是 refresh(),而不是 init() 這種名字的方法。因為 ApplicationContext 建立起來以后,其實我們是可以通過調用 refresh() 這個方法重建的,refresh() 會將原來的 ApplicationContext 銷毀,然后再重新執行一次初始化操作。

為什么是 refresh() 而不是 init()?

  1. ApplicationContext 生命周期管理

    • ApplicationContext 在被創建后,其生命周期可能會涉及到多個階段和狀態變化。init() 通常用于單個 Bean 的初始化階段,而不是整個 ApplicationContext 的初始化和刷新過程。

  2. Spring IoC 容器的特性

    • Spring IoC 容器的初始化不僅僅是單純地實例化 Bean,還包括資源加載、依賴注入、生命周期管理等復雜的操作。refresh() 方法能夠確保在容器需要更新時,能夠重新加載所有配置,而不僅僅是執行初始化操作。

  3. Bean 的生命周期與容器的生命周期分離

    • Spring 設計中,Bean 的生命周期由容器管理,而不同于容器本身的生命周期。因此,ApplicationContext 提供了 refresh() 方法,來明確表達容器狀態的刷新,與單個 Bean 的初始化操作不同。

  4. 清晰的語義

    • refresh() 方法的名稱清晰地表明了它的功能:刷新容器的狀態。這比簡單的 init() 方法更具描述性和準確性,能夠讓開發人員清晰地理解其作用,從而更好地管理 ApplicationContext 的生命周期。

創建 Bean 容器前的準備工作

?protected void prepareRefresh() {

創建 Bean 容器,加載并注冊 Bean

?protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
? ? // 關閉舊的 BeanFactory (如果有),創建新的 BeanFactory,加載 Bean 定義、注冊 Bean 等等
? ? refreshBeanFactory();

初始化 BeanFactory

?protected final void refreshBeanFactory() throws BeansException 

注意,這個方法是全文最重要的部分之一,這里將會初始化 BeanFactory、加載 Bean、注冊 Bean 等等。

當然,這步結束后,Bean 并沒有完成初始化。這里指的是 Bean 實例并未在這一步生成。

ApplicationContext 繼承自 BeanFactory,但是它不應該被理解為 BeanFactory 的實現類,而是說其內部持有一個實例化的 BeanFactory(DefaultListableBeanFactory)。以后所有的 BeanFactory 相關的操作其實是委托給這個實例來處理的。

obtainFreshBeanFactory()

refresh() 方法中,obtainFreshBeanFactory() 負責獲取一個全新的Bean工廠實例,也就是 BeanFactory 的初始化過程。這一步驟涉及以下關鍵操作:

  • 創建BeanFactory實例: Spring 使用 DefaultListableBeanFactory 或其子類作為默認的 BeanFactory 實現。這個過程通常由 createBeanFactory() 方法完成,它會創建一個新的 DefaultListableBeanFactory 實例。

?javaCopy Codeprotected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
? ?  // 創建一個新的BeanFactory實例
? ?  refreshBeanFactory();
? ?  ConfigurableListableBeanFactory beanFactory = getBeanFactory();
? ?  // 設置BeanFactory的類加載器等屬性
? ?  customizeBeanFactory(beanFactory);
? ?  return beanFactory;
?}
2. 加載Bean定義

一旦 BeanFactory 初始化完成,接下來的步驟是加載Bean的定義信息。這些定義通常來源于配置文件(如XML文件)、注解或者基于Java的配置類。Spring 使用不同的 BeanDefinitionReader 實現類(如 XmlBeanDefinitionReaderAnnotatedBeanDefinitionReader 等)來讀取這些定義并將其注冊到 BeanFactory 中。

?javaCopy Codeprotected void refreshBeanFactory() throws BeansException {
? ?  if (hasBeanFactory()) {
? ? ? ?  destroyBeans();
? ? ? ?  closeBeanFactory();
? ?  }
? ?  try {
? ? ? ?  DefaultListableBeanFactory beanFactory = createBeanFactory();
? ? ? ?  // 加載Bean定義
? ? ? ?  loadBeanDefinitions(beanFactory);
? ? ? ?  this.beanFactory = beanFactory;
? ?  }
? ?  catch (IOException ex) {
? ? ? ?  throw new ApplicationContextException("I/O error parsing bean definition source", ex);
? ?  }
?}
3. 注冊Bean定義

loadBeanDefinitions(beanFactory) 方法負責將解析后的Bean定義注冊到 BeanFactory 中。這一步包括解析XML文件、掃描類路徑、處理注解等操作,最終將每個Bean的定義信息(包括類名、依賴關系、初始化方法等)存儲在 BeanFactory 的內部數據結構中。

?javaCopy Codeprotected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
? ?  // 創建Bean定義讀取器
? ?  BeanDefinitionReader beanDefinitionReader = createBeanDefinitionReader(beanFactory);
? ?  // 加載Bean定義,具體實現依賴于Bean定義讀取器的實現類
? ?  loadBeanDefinitions(beanDefinitionReader, beanFactory);
?}
4. Bean實例化與初始化

refresh() 方法的后續步驟中,當應用程序需要使用某個Bean時,Spring IoC容器會根據Bean的定義信息(包括類、依賴關系等)實例化相應的Bean對象。這個過程通常發生在 getBean() 方法調用時。

  • 依賴注入: 在Bean實例化后,Spring會通過依賴注入機制將所需的依賴項自動注入到Bean中。

  • 初始化方法: 如果Bean類實現了 InitializingBean 接口或者在配置中指定了初始化方法(如 init-method 屬性),Spring會在實例化和依賴注入完成后調用這些方法。

總結

refresh() 方法中,obtainFreshBeanFactory() 的作用是獲取一個新的 BeanFactory 實例并初始化它,包括加載和注冊Bean的定義。雖然在這個階段,Bean的實例并沒有完成初始化,但是這一步驟為后續的Bean實例化和依賴注入做了準備。理解這些步驟有助于我們了解Spring IoC容器是如何管理Bean的生命周期和依賴關系的。

gpt總結

理解Spring IoC容器的完整流程需要深入研究其底層源碼,特別是核心模塊spring-contextspring-beans。以下是一個簡化的版本,涵蓋了主要的步驟和關鍵類,以便于理解IoC容器的工作原理:

1. 加載配置元數據

Spring IoC容器通常從XML配置文件或基于Java的配置類中加載配置元數據。假設我們有一個簡單的配置文件applicationContext.xml

?xmlCopy Code<beans xmlns="http://www.springframework.org/schema/beans"
? ? ? ? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
? ? ? ? xsi:schemaLocation="http://www.springframework.org/schema/beans
? ? ? ? ? ? ? ? ? ? ? ? ? ? http://www.springframework.org/schema/beans/spring-beans.xsd">
??
? ?  <bean id="userService" class="com.example.UserService">
? ? ? ?  <!-- 依賴注入 -->
? ? ? ?  <property name="userDao" ref="userDao"/>
? ?  </bean>
??
? ?  <bean id="userDao" class="com.example.UserDaoImpl"/>
? ? ?
?</beans>

2. 解析Bean定義

Spring IoC容器在加載配置文件時,會使用XML解析器解析XML文件并提取Bean定義信息。關鍵類包括XmlBeanDefinitionReader

?javaCopy Codepublic class XmlBeanDefinitionReader {
? ? ?
? ?  private BeanDefinitionRegistry registry;
? ? ?
? ?  public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
? ? ? ?  this.registry = registry;
? ?  }
? ? ?
? ?  public void loadBeanDefinitions(Resource resource) {
? ? ? ?  // 解析XML資源并注冊Bean定義
? ? ? ?  // 例如從XML中讀取<bean>標簽,創建對應的BeanDefinition對象
? ?  }
? ? ?
? ?  // 省略其他方法
?}

3. 注冊Bean定義

注冊過程由BeanDefinitionRegistry接口及其實現類負責,通常使用DefaultListableBeanFactory

?javaCopy Codepublic class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
? ? ? ?  implements ConfigurableListableBeanFactory, BeanDefinitionRegistry {
??
? ?  private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
??
? ?  @Override
? ?  public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
? ? ? ? ? ?  throws BeanDefinitionStoreException {
? ? ? ?  // 將BeanDefinition注冊到容器中
? ? ? ?  beanDefinitionMap.put(beanName, beanDefinition);
? ?  }
??
? ?  // 省略其他方法
?}

4. 實例化Bean

當應用程序需要獲取Bean時,通過Bean工廠獲取Bean的實例。關鍵類包括DefaultListableBeanFactory中的getBean()方法:

?javaCopy Codepublic class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
? ? ? ?  implements ConfigurableListableBeanFactory, BeanDefinitionRegistry {
??
? ?  @Override
? ?  protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)
? ? ? ? ? ?  throws BeanCreationException {
? ? ? ?  // 使用反射創建Bean的實例
? ? ? ?  // 根據BeanDefinition中的信息,實例化Bean對象
? ?  }
??
? ?  @Override
? ?  public Object getBean(String name) throws BeansException {
? ? ? ?  // 從容器中獲取Bean實例
? ? ? ?  return doGetBean(name, null, null, false);
? ?  }
??
? ?  // 省略其他方法
?}

5. 依賴注入

依賴注入是IoC容器的核心功能之一,通過反射或其他手段將Bean所需的依賴注入到Bean中。Spring使用AutowiredAnnotationBeanPostProcessor等后置處理器來實現依賴注入:

?javaCopy Codepublic class AutowiredAnnotationBeanPostProcessor implements BeanPostProcessor {
? ? ?
? ?  @Override
? ?  public Object postProcessProperties(Object bean, String beanName) throws BeansException {
? ? ? ?  // 通過反射掃描Bean的屬性,解析@Autowired等注解,并進行依賴注入
? ?  }
??
? ?  // 省略其他方法
?}

6. 生命周期管理

Spring IoC容器還管理Bean的生命周期,包括初始化和銷毀。例如,AbstractAutowireCapableBeanFactory負責調用Bean的初始化方法和銷毀方法

BeanPostProcessor 的實現類,注意看和 BeanFactoryPostProcessor 的區別

區別總結

  • 執行時機

    • BeanFactoryPostProcessor 在 Spring 容器實例化 BeanDefinition 之后、實例化 Bean 之前執行。

    • BeanPostProcessor 在 Bean 實例化之后、依賴注入完成之前執行。

  • 作用對象

    • BeanFactoryPostProcessor 作用于 BeanDefinition 的元數據,可以影響 Spring 容器中所有 Bean 的創建過程。

    • BeanPostProcessor 作用于具體的 Bean 實例,只影響特定的 Bean 實例。

  • 典型用途

    • BeanFactoryPostProcessor 用于對 BeanFactory 的配置進行修改,如動態注冊 Bean。

    • BeanPostProcessor 用于在 Bean 的初始化過程中進行額外的處理,如 AOP 代理的創建。

綜上所述,BeanFactoryPostProcessor 和 BeanPostProcessor 是 Spring 中用于定制和擴展 Bean 實例化過程的重要接口,各自在不同階段提供了不同的擴展能力。

BeanFactoryPostProcessor 接口允許我們在 Spring 容器實例化了 BeanDefinition(即配置元數據)之后,在實例化具體的 Bean 對象之前對其進行后處理。這意味著它可以在 Spring IOC 容器讀取了所有的配置元數據(包括 Bean 的定義和屬性)后,在實例化任何 Bean 之前介入。

具體來說:

  1. BeanDefinition 解析和注冊階段: 在 Spring 啟動時,容器會讀取配置文件或者注解等配置元數據,并根據這些信息創建對應的 BeanDefinition 對象,這些對象描述了每個 Bean 的定義、類型、依賴關系等信息。

  2. BeanFactoryPostProcessor 的介入: 在 BeanDefinition 注冊完成之后,容器會調用注冊的 BeanFactoryPostProcessor 實現類的方法。這時,BeanFactoryPostProcessor 可以查看并修改容器中的 BeanDefinition,但還沒有實例化任何 Bean。

  3. Bean 實例化階段: 一旦所有注冊的 BeanFactoryPostProcessor 執行完畢,容器就會根據 BeanDefinition 實例化具體的 Bean 對象,并進行依賴注入等后續處理。

因此,BeanFactoryPostProcessor 提供了一個在 Spring 容器準備實例化 Bean 之前修改 BeanDefinition 的機會,但它并不直接處理實際的 Bean 實例。這種機制允許我們在 Spring 容器加載配置信息后,但在實例化 Bean 之前,對容器中的 BeanDefinition 進行修改或者擴展,以滿足特定的需求或者進行定制化配置

BeanFactory 和 FactoryBean的區別

在 Spring 框架中,有兩個與 IoC 容器相關的重要概念:FactoryBean 和 BeanFactory。它們雖然名字相似,但是在 Spring 中扮演的角色和功能卻有所不同。

BeanFactory

BeanFactory 是 Spring IoC 容器的核心接口之一。它提供了 IoC 容器最基本的功能,包括:

  1. Bean 實例化:負責根據配置信息實例化 bean 對象。

  2. 依賴注入:將 bean 的依賴關系動態注入到對象中,實現松耦合。

  3. 生命周期管理:管理 bean 的生命周期,包括初始化和銷毀。

  4. 配置管理:讀取和解析配置元數據,包括 bean 的定義、作用域、屬性等。

BeanFactory 的實現類通常包括 DefaultListableBeanFactoryXmlBeanFactory 等,它們是 Spring IoC 容器的具體實現。BeanFactory 采用延遲加載策略,即在第一次請求時才會實例化 bean,從而節省資源。

實例化bean和初始化bean是一個概念嗎

實例化Bean和初始化Bean是兩個相關但不完全相同的概念。

  1. 實例化Bean

    • 實例化Bean是指在容器中創建Bean的實際對象。這通常發生在容器根據Bean的定義信息(如類路徑、構造函數參數等)使用反射或其他手段創建Bean的實例的過程。

    • 實例化過程確保了容器可以通過Bean的定義來創建具體的對象,但此時還未涉及到依賴注入或其他初始化操作。

  2. 初始化Bean

    • 初始化Bean是指在實例化之后,容器對Bean進行額外的處理和配置,以使Bean處于可用狀態。這包括依賴注入、調用初始化方法、應用BeanPostProcessors等操作。

    • 初始化過程確保了Bean的各種依賴已經被注入,并且Bean處于一種可以被應用程序使用的狀態。

在Spring IoC容器中,這兩個過程是逐步進行的:

  • 實例化Bean:容器根據Bean的定義創建Bean的實例對象。

  • 初始化Bean:容器對實例化后的Bean進行依賴注入、初始化方法調用等操作,確保Bean準備好被應用程序使用。

因此,雖然它們通常在文檔或討論中一起提到,但它們確實表示兩個不

FactoryBean

FactoryBean 是一個特殊的 bean,它本身是一個工廠類,用來創建或管理其他的 bean 實例。在 Spring 中,FactoryBean 接口定義了創建 bean 實例的標準方法和生命周期。通常,我們可以通過兩種方式來實現 FactoryBean:

  1. 通過實現 FactoryBean 接口:自定義一個類,實現 FactoryBean 接口,并在其實現方法中定義 bean 的創建邏輯。

    ?javaCopy Codepublic class MyFactoryBean implements FactoryBean<MyBean> {
    ? ?  @Override
    ? ?  public MyBean getObject() throws Exception {
    ? ? ? ?  // 返回創建的 bean 實例
    ? ? ? ?  return new MyBean();
    ? ?  }
    ? ? ?
    ? ?  @Override
    ? ?  public Class<?> getObjectType() {
    ? ? ? ?  return MyBean.class;
    ? ?  }
    ? ? ?
    ? ?  @Override
    ? ?  public boolean isSingleton() {
    ? ? ? ?  return true; // true 表示該 bean 是單例的
    ? ?  }
    ?}
  2. 通過繼承 Spring 提供的抽象類:Spring 提供了幾個抽象類,如 AbstractFactoryBean,簡化了 FactoryBean 的實現。

FactoryBean 提供了一種非常靈活的方式來定義 bean 的創建過程,允許開發者在獲取 bean 實例之前執行一些定制化的邏輯。它常用于復雜的對象創建、資源管理或者代理對象的創建。

區別總結

  • BeanFactory 是 Spring IoC 容器的核心接口,負責管理 bean 的生命周期、依賴注入等基礎功能。

  • FactoryBean 是一個特殊的 bean,它本身是一個工廠,用來創建或管理其他的 bean 實例。通過實現 FactoryBean 接口或者繼承 Spring 提供的抽象類,可以定制化 bean 的創建過程。

在實際應用中,開發者可以根據需要選擇合適的方式來定義和管理 bean,以實現更靈活、可維護和可測試的代碼。

FactoryBean 接口在 Spring 中被廣泛用于定義復雜或者特殊需求的 bean 創建過程。以下是一些比較出名的組件或模塊,它們利用了 FactoryBean 接口來實現自定義的 bean 創建邏輯:

  1. HibernateTemplate

    • HibernateTemplate 是 Spring 提供的一個簡化 Hibernate 數據訪問的類,它通過實現 FactoryBean 接口來創建 SessionFactoryHibernateTemplate 對象。這種方式使得 Hibernate 的配置和管理變得更加靈活,允許開發者在創建時進行一些自定義的初始化操作。

javaCopy Codepublic class HibernateTemplateFactoryBean implements FactoryBean<HibernateTemplate>, InitializingBean {
? ? private SessionFactory sessionFactory;
? ? private HibernateTemplate hibernateTemplate;

? ? public void setSessionFactory(SessionFactory sessionFactory) {
? ? ? ? this.sessionFactory = sessionFactory;
? ? }

? ? @Override
? ? public HibernateTemplate getObject() throws Exception {
? ? ? ? return this.hibernateTemplate;
? ? }

? ? @Override
? ? public Class<?> getObjectType() {
? ? ? ? return HibernateTemplate.class;
? ? }

? ? @Override
? ? public boolean isSingleton() {
? ? ? ? return true;
? ? }

? ? @Override
? ? public void afterPropertiesSet() {
? ? ? ? this.hibernateTemplate = new HibernateTemplate(this.sessionFactory);
? ? ? ? // 可以進行其他的初始化操作
? ? }

原文鏈接:https://blog.csdn.net/lifan123acd/article/details/140486485

  • 上一篇:沒有了
  • 下一篇:沒有了
欄目分類
最近更新