51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Spring 中的 ApplicationContext

1、概览 {#1概览}

本文将带你详细了解 Spring 中的 ApplicationContext 接口。

2、ApplicationContext 接口 {#2applicationcontext-接口}

Spring 框架的主要功能之一是 IoC(控制反转)容器。Spring IoC 容器负责管理应用的对象。它使用依赖注入来实现控制反转。

BeanFactoryApplicationContext 接口,代表 Spring IoC 容器。其中,BeanFactory 是访问 Spring 容器的根接口。它提供了管理 Bean 的基本功能。

ApplicationContextBeanFactory 的子接口。因此,它具备 BeanFactory 的所有功能。

此外,它还提供了更多面向企业的特定功能。ApplicationContext 的重要功能包括解析消息、支持国际化、发布事件以及应用层特定的上下文。这就是为什么我们将其作为默认的 Spring 容器使用的原因。

3、Spring Bean 是什么? {#3spring-bean-是什么}

在深入了解 ApplicationContext 容器之前,有必要了解一下 Spring Bean。在 Spring 中,Bean 是 Spring 容器实例化、组装和管理的对象。

那么,是否应该将应用的所有对象都配置为 Spring Bean 呢?作为最佳实践,不应该这样做。

一般来说,根据 Spring 文档 所述,应该为服务层对象、数据访问对象 (DAO)、表现对象、基础架构对象(如 Hibernate SessionFactory、JMS Queue 等)定义 Bean。

此外,通常情况下,不应该在容器中配置细粒度的 Domain 对象。创建和加载 Domain 对象通常是 DAO 和业务逻辑的职责。

定义一个简单的 Java 类,在本文中用作 Spring Bean:

public class AccountService {

  @Autowired
  private AccountRepository accountRepository;

  // Get、Set 方法省略
}

4、在容器中配置 Bean {#4在容器中配置-bean}

我们知道,ApplicationContext 的主要工作是管理 Bean。

因此,应用必须向 ApplicationContext 容器提供 Bean 配置。Spring Bean 配置由一个或多个 Bean 定义(Definition)组成。此外,Spring 还支持不同的 Bean 配置方式。

4.1、基于 Java 的配置 {#41基于-java-的配置}

首先,从基于 Java 的配置开始,因为它是最受欢迎的 Bean 配置方式,从 Spring 3.0 开始可用。

Java 配置通常在 @Configuration 类中使用 @Bean 注解方法。方法上的 @Bean 注解表示该方法创建了一个 Spring Bean。此外,被 @Configuration 注解标记的类表示它包含 Spring Bean 的配置信息。

创建一个配置类,将 AccountService 类定义为 Spring Bean:

@Configuration
public class AccountConfig {

  @Bean
  public AccountService accountService() {
    return new AccountService(accountRepository());
  }

  @Bean
  public AccountRepository accountRepository() {
    return new AccountRepository();
  }
}

4.2、基于注解的配置 {#42基于注解的配置}

Spring 2.5 引入了基于注解的配置。

在这种方法中,首先通过 XML 配置启用基于注解的配置。然后,在 Java 类、方法、构造函数或字段上使用一组注解来配置 Bean。这些注解的一些示例包括 @Component@Controller@Service@Repository@Autowired@Qualifier

注意,我们在基于 Java 的配置中也使用了这些注解。另外,Spring 每次发布都可能会为这些注解添加更多功能。

来看一个简单的示例。

首先,创建 XML 配置 user-bean-config.xml,以启用注解:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
  
  <context:annotation-config/>
  <context:component-scan base-package="com.baeldung.applicationcontext"/>

</beans>

如上,annotation-config 标签启用了基于注解的映射。component-scan(组件扫描)标签还告诉 Spring 在哪里查找注解类。

其次,创建 UserService 类,并使用 @Component 注解将其定义为 Spring Bean:

@Component
public class UserService {
  // UserService 代码
}

然后,编写一个简单的测试用例来测试此配置:

ApplicationContext context = new ClassPathXmlApplicationContext("applicationcontext/user-bean-config.xml");
UserService userService = context.getBean(UserService.class);
assertNotNull(userService);

4.3、基于 XML 的配置 {#43基于-xml-的配置}

最后,来看看基于 XML 的配置。这是 Spring 中配置 Bean 的传统方法。

显然,在这种方法中,需要在 XML 配置文件中完成所有 Bean 映射。

创建一个 XML 配置文件 account-bean-config.xml,并把 AccountService 类定义为 Bean:

<?xml version="1.0" encoding="UTF-8"?>
<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="accountService" class="com.baeldung.applicationcontext.AccountService">
    <constructor-arg name="accountRepository" ref="accountRepository" />
  </bean>

  <bean id="accountRepository" class="com.baeldung.applicationcontext.AccountRepository" />
</beans>

5、ApplicationContext 类型 {#5applicationcontext-类型}

Spring 提供了适合不同需求的不同类型的 ApplicationContext 容器。这些都是 ApplicationContext 接口的实现。

下面就来看看 ApplicationContext 的一些常见类型。

5.1、AnnotationConfigApplicationContext {#51annotationconfigapplicationcontext}

首先,看看在 Spring 3.0 中引入的 AnnotationConfigApplicationContext 类。它可以将使用 @Configuration@Component 和 JSR-330 元数据注解的类作为输入。

使用 AnnotationConfigApplicationContext 容器和基于 Java 配置的简单示例:

ApplicationContext context = new AnnotationConfigApplicationContext(AccountConfig.class);
AccountService accountService = context.getBean(AccountService.class);

5.2、AnnotationConfigWebApplicationContext {#52annotationconfigwebapplicationcontext}

AnnotationConfigWebApplicationContextAnnotationConfigApplicationContext 的 Web 版。

当在 web.xml 文件中配置 Spring 的 ContextLoaderListener 监听器或 Spring MVC DispatcherServlet 时,可能会用到该类。

从 Spring 3.0 开始,还可以以编程式配置此 Application Context 容器。只需实现 WebApplicationInitializer 接口即可:

public class MyWebApplicationInitializer implements WebApplicationInitializer {

  public void onStartup(ServletContext container) throws ServletException {
    AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
    context.register(AccountConfig.class);
    context.setServletContext(container);

    // servlet 配置
  }
}

5.3、XmlWebApplicationContext {#53xmlwebapplicationcontext}

如果在 Web 应用中使用基于 XML 的配置,可以使用 XmlWebApplicationContext 类。

事实上,配置该容器的方法与 AnnotationConfigWebApplicationContext 类一样,也就是说,可以在 web.xml 中进行配置,或者实现 WebApplicationInitializer 接口:

public class MyXmlWebApplicationInitializer implements WebApplicationInitializer {

  public void onStartup(ServletContext container) throws ServletException {
    XmlWebApplicationContext context = new XmlWebApplicationContext();
    context.setConfigLocation("/WEB-INF/spring/applicationContext.xml");
    context.setServletContext(container);

    // Servlet 配置
  }
}

5.4、FileSystemXMLApplicationContext {#54filesystemxmlapplicationcontext}

使用 FileSystemXMLApplicationContext 类从文件系统或 URL 加载基于 XML 的 Spring 配置文件。当需要以编程方式加载 ApplicationContext 时,该类就会派上用场。通常用于测试场景或者是独立应用。

创建这个 Spring 容器并加载基于 XML 的配置中的 Bean:

String path = "C:/myProject/src/main/resources/applicationcontext/account-bean-config.xml";

ApplicationContext context = new FileSystemXmlApplicationContext(path);
AccountService accountService = context.getBean("accountService", AccountService.class);

5.5、ClassPathXmlApplicationContext {#55classpathxmlapplicationcontext}

如果想从 classpath 加载 XML 配置文件,可以使用 ClassPathXmlApplicationContext 类。该类与 FileSystemXMLApplicationContext 类似,适用于测试环境以及嵌入在 JAR 中的 Application Context。

示例如下:

ApplicationContext context = new ClassPathXmlApplicationContext("applicationcontext/account-bean-config.xml");
AccountService accountService = context.getBean("accountService", AccountService.class);

6、ApplicationContext 的其他功能 {#6applicationcontext-的其他功能}

6.1、Message 解析 {#61message-解析}

ApplicationContext 接口通过继承 MessageSource 接口来支持消息解析和国际化。此外,Spring 还提供了两种 MessageSource 实现,即 ResourceBundleMessageSourceStaticMessageSource

我们可以使用 StaticMessageSource 以编程式将消息添加到消息源中;但是,它仅支持基本的国际化,更适合用于测试而非生产环境。

ResourceBundleMessageSourceMessageSource 最常见的实现。它依赖于底层 JDK 的 ResourceBundle 实现,并使用 JDK 提供的标准消息解析(MessageFormat)。

来看看如何使用 MessageSource 从 properties 文件中读取消息。

首先,在 classpath 上创建 messages.properties 文件:

account.name=TestAccount

其次,在 AccountConfig 类中添加一个 Bean 定义:

@Bean
public MessageSource messageSource() {
  ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
  messageSource.setBasename("config/messages");
  return messageSource;
}

接着,在 AccountService 中注入 MessageSource

@Autowired
private MessageSource messageSource;

最后,可以在 AccountService 的任何地方使用 getMessage 方法来读取消息:

messageSource.getMessage("account.name", null, Locale.ENGLISH);

Spring 还提供了 ReloadableResourceBundleMessageSource 类,该类允许从任何 Spring Resource 位置读取文件,并支持热重载 Bundle 属性文件。

6.2、事件处理 {#62事件处理}

ApplicationContext 通过 ApplicationEvent 类和 ApplicationListener 接口支持事件处理。它除了支持 ContextStartedEventContextStoppedEventContextClosedEventRequestHandledEvent 等内置事件外,还支持在业务中自定义的事件。

更多关于 Spring 事件处理的详细内容,你可以参阅 这篇文章

7、总结 {#7总结}

本文详细介绍了 Spring 中 ApplicationContext 容器,以及如何在 AppicationContext 中配置 Spring Bean。最介绍了如何创建和使用不同类型的 ApplicationContext


Ref:https://www.baeldung.com/spring-application-context

赞(2)
未经允许不得转载:工具盒子 » Spring 中的 ApplicationContext