[Java] 深入理解:Spring Context :Spring 上下文(ApplicationContext)的層次結構

千千寰宇發表於2024-10-11

前言

在使用 Spring 框架進行應用程式開發時,Spring 上下文(Context)是一個非常重要的概念。
Spring 上下文提供了一個環境,用於管理應用程式中的物件(通常稱為 Bean)及其之間的依賴關係
在複雜的應用程式中,可能存在多個上下文物件,而這些上下文物件之間可以形成一種層次結構
本文將深入探討 Spring 上下文的層次結構,並介紹如何在實際專案中應用這種結構。

1 什麼是 Spring 上下文(Context)

在 Spring 框架中,上下文(Context)是一個重要的概念,它代表了 Spring 容器中的一個環境,負責管理 Bean 物件及其之間的依賴關係。
Spring 上下文可以從 XML 檔案、Java 註解或者 Java 程式碼中載入配置資訊,並將這些配置資訊轉換成應用程式中的物件。
通常情況下,我們使用 ApplicationContext 介面來表示 Spring 上下文

2 什麼是上下文層次結構

在大型的應用程式中,可能存在多個模組或者子系統,它們之間存在依賴關係,並且可能共享一些資源或者配置資訊。
為了更好地管理這些依賴關係和資源,Spring 引入了上下文層次結構的概念。
上下文層次結構允許我們在應用程式中建立多個上下文物件,並且這些上下文物件之間存在父子關係,從而形成一個層次結構。

3 Spring 上下文層次結構的組成

Spring 上下文層次結構通常由一個頂層的父上下文和多個子上下文組成。
父上下文負責管理一些全域性性的資源和配置資訊,而子上下文則負責管理特定於某個模組或子系統的資源和配置資訊。
子上下文可以訪問父上下文中定義的 Bean 物件和配置資訊,從而實現資源的共享和依賴的管理。

4 如何使用 Spring 上下文層次結構

在實際專案中,我們可以透過 XML 檔案或者 Java 程式碼來配置 Spring 上下文的層次結構。

首先,我們需要定義父上下文中的配置資訊,包括共享的資源和配置資訊
然後,我們可以建立子上下文,並且透過構造方法或者 setParent() 方法將父上下文與子上下文關聯起來。
最後,我們可以在子上下文中定義特定於該子系統或者模組的 Bean 物件,並且可以透過依賴注入的方式來獲取這些 Bean 物件。

Spring 上下文的層次結構使用流程:

// 定義一個父上下文的配置類
public class ParentContextConfig {
    // 省略配置資訊
}

// 定義一個子上下文的配置類
public class ChildContextConfig {
    // 省略配置資訊
}
public class Main {
    public static void main(String[] args) {
        // 建立父上下文
        AnnotationConfigApplicationContext parentContext = new AnnotationConfigApplicationContext();
        parentContext.register(ParentContextConfig.class);
        parentContext.refresh();

        // 建立子上下文,設定其父上下文
        AnnotationConfigApplicationContext childContext = new AnnotationConfigApplicationContext();
        childContext.register(ChildContextConfig.class);
        childContext.setParent(parentContext);
        childContext.refresh();

        // 在子上下文中獲取 bean
        SomeBean bean = childContext.getBean(SomeBean.class);

        // 關閉上下文
        childContext.close();
        parentContext.close();
    }
}

5 Spring MVC 中的上下文層次結構

Spring 上下文層次結構最經典的一個應用,便是在 Spring MVC 中。

首先,假設我們有一個全域性應用程式配置類 AppConfig 和一個 Servlet 配置類 ServletConfig。

@Configuration
public class AppConfig {
    @Bean
    public DataSource dataSource() {
        // 返回資料來源配置
    }

    @Bean
    public TransactionManager transactionManager() {
        // 返回事務管理器配置
    }
}

.

@Configuration
public class ServletConfig {
    @Autowired
    private DataSource dataSource; // 從全域性應用程式上下文中注入資料來源
    
    @Autowired
    private TransactionManager transactionManager; // 從全域性應用程式上下文中注入事務管理器
    
    @Bean
    public SomeService someService() {
        // 返回服務 Bean 配置,可能需要使用全域性資料來源和事務管理器
    }
}

然後,在應用程式初始化時,我們可以建立全域性應用程式上下文和 Servlet 上下文。

public class MyAppInitializer implements WebApplicationInitializer {
    
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        // 建立全域性應用程式上下文
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(AppConfig.class);
        servletContext.addListener(new ContextLoaderListener(rootContext));

        // 建立 Servlet 上下文
        AnnotationConfigWebApplicationContext servletContext = new AnnotationConfigWebApplicationContext();
        servletContext.setParent(rootContext); // 將全域性應用程式上下文設定為父上下文
        servletContext.register(ServletConfig.class);
        
        // 將 Servlet 上下文註冊到 Servlet 容器中
        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(servletContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }

6 小結

透過 Spring 上下文的層次結構,我們可以更好地管理應用程式中的依賴關係和資源,提高了程式碼的模組化和可維護性。在實際專案中,合理地使用上下文層次結構可以帶來很多好處,例如資源共享、依賴隔離以及作用域管理等。

Y 推薦文獻

  • Spring 三級快取 - CSDN
  • 深入瞭解 MyBatis 外掛:定製化你的持久層框架 - CSDN

X 參考文獻

  • 【Spring】深入理解 Spring 上下文(Context)層次結構 - CSDN

相關文章