【Spring】8.深入探索Spring Context:由浅入深直击Spring的心脏

2024-05-04 16:28

本文主要是介绍【Spring】8.深入探索Spring Context:由浅入深直击Spring的心脏,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Spring Context 是 Spring 框架中的一个核心组件,负责提供 Spring 应用的运行时环境。Context 表示“上下文”或“环境”,在 Spring 中,它不仅管理着应用中的对象(称为 Beans),还提供了许多其他关键服务,这些服务对于构建企业级应用至关重要。

作用

  1. IoC 容器:作为控制反转(IoC)容器,Spring Context 负责创建、配置、组装和销毁 Beans。它通过依赖注入(DI)管理对象之间的依赖关系。

  2. 资源管理:提供对外部资源的访问,如数据库连接、文件、网络资源等。

  3. 事件机制:支持事件发布和监听机制,允许应用组件之间通过事件进行通信。

  4. 国际化:支持基于区域的资源文件管理,实现多语言国际化。

  5. 事务管理:提供声明式和编程式的事务管理,支持对事务的细粒度控制。

  6. 安全性:与 Spring Security 集成,提供认证和授权等安全功能。

  7. 数据访问:支持对各种数据访问技术的集成,如 JDBC、Hibernate、JPA 等。

  8. 模块化:支持模块化的应用程序设计,允许应用按模块进行组织和部署。

  9. 扩展点:提供多个扩展点,如 BeanFactoryPostProcessorBeanPostProcessor,允许开发者自定义容器的行为。

  10. 上下文信息:提供关于 Bean 的上下文信息,如 Bean 的定义、作用域和生命周期。

重要性

  • 解耦:通过 IoC 容器,Spring Context 帮助实现了对象之间的松耦合,使得应用更易于管理和维护。
  • 灵活性:提供了灵活的配置和扩展机制,使得应用可以根据需求快速适应变化。
  • 企业级支持:提供了企业级应用开发所需的各种服务和支持,如事务管理、安全性、消息传递等。
  • 集成性:Spring Context 可以很容易地与 Spring 框架的其他模块如 Spring MVC、Spring Data 等集成,构建全栈式的 Java 应用。

总的来说,Spring Context 是 Spring 框架的心脏,为整个应用提供动力和环境支持,是构建和管理企业级 Java 应用的基础。

ApplicationContext接口的实现

ApplicationContext 接口在Spring框架中是用于提供应用上下文的接口,它定义了一系列获取应用环境信息、消息解析、事件发布等基本操作。以下是几种常用的 ApplicationContext 接口实现,以及它们各自的作用和源码片段:

  1. ClassPathXmlApplicationContext
    作用:这个实现从类路径(ClassPath)中加载XML配置文件来初始化Spring上下文。它是最常用的上下文实现之一,特别适合于独立的Java应用程序。
    源码片段

    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    // 这里可以获取配置在applicationContext.xml中的Bean
    MyBean myBean = context.getBean(MyBean.class);
    
  2. FileSystemXmlApplicationContext
    作用:这个实现从文件系统的指定位置加载XML配置文件来初始化Spring上下文。它适用于需要从外部文件系统加载配置文件的场景。
    源码片段

    ApplicationContext context = new FileSystemXmlApplicationContext("/path/to/applicationContext.xml");
    // 获取Bean
    MyBean myBean = context.getBean(MyBean.class);
    
  3. AnnotationConfigApplicationContext
    作用:这个实现用于基于注解的配置。它不依赖于XML文件,而是使用Java注解来配置Bean,适用于现代Spring应用程序,特别是当与Spring Boot结合使用时。
    源码片段

    ApplicationContext context = new AnnotationConfigApplicationContext();
    context.register(AppConfig.class); // AppConfig是一个带有@Configuration注解的类
    context.refresh();
    // 获取Bean
    MyBean myBean = context.getBean(MyBean.class);
    
  4. AnnotationConfigWebApplicationContext
    作用:这是AnnotationConfigApplicationContext的Web版本,用于Web应用程序。它可以与Servlet容器集成,用于Spring MVC等Web应用。
    源码片段

    public class MyWebApplicationInitializer implements WebApplicationInitializer {public void onStartup(ServletContext container) {AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();context.register(AppConfig.class);context.setServletContext(container);// 其他servlet配置}
    }
    
  5. GenericApplicationContext
    作用:这是一个通用的Spring应用上下文实现,可以与各种BeanDefinitionReaderBeanFactoryPostProcessor配合使用,用于动态添加Bean定义。

    • 源码片段
      GenericApplicationContext ctx = new GenericApplicationContext();
      XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
      xmlReader.loadBeanDefinitions(new ClassPathResource("applicationContext.xml"));
      ctx.refresh();
      // 获取Bean
      MyBean myBean = ctx.getBean(MyBean.class);
      
  6. StaticApplicationContext
    作用:这个实现主要用于编程式的注入Bean和消息,而不是从外部的配置源读取Bean的定义。它通常用于测试环境,因为它允许以声明式的方式添加Beans。
    源码片段

    StaticApplicationContext applicationContext = new StaticApplicationContext();
    applicationContext.registerBean(User.class);
    applicationContext.refresh();
    // 获取Bean
    User user = applicationContext.getBean(User.class);
    

这些实现覆盖了从传统的基于XML的配置到现代的注解和编程式配置的多种应用场景。可以根据项目需求和偏好选择合适的上下文实现。

Spring Context的配置

配置Spring Context可以通过XML文件或Java注解来完成。以下是两种配置方式的基本步骤:

通过XML配置

  1. 创建XML配置文件:首先,在项目中创建一个XML文件,比如命名为applicationContext.xml

  2. 定义Beans:在XML文件中定义所需的Beans,指定它们的类、属性和依赖。

  3. 指定配置文件位置:在启动Spring应用时,需要指定XML配置文件的位置。

  4. 初始化Spring Context:使用ClassPathXmlApplicationContextFileSystemXmlApplicationContext来加载配置文件并初始化Spring Context。

示例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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="myBean" class="com.example.MyBean"><property name="dependency" ref="dependencyBean"/></bean><bean id="dependencyBean" class="com.example.DependencyBean"/>
</beans>

初始化Context

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MyBean myBean = context.getBean(MyBean.class);

通过注解配置

  1. 添加注解驱动的配置类:创建一个带有@Configuration注解的类,定义Bean。

  2. 使用@Bean注解:在配置类中,使用@Bean注解方法来声明Spring管理的Beans。

  3. 组件扫描:使用@ComponentScan注解指定Spring扫描组件的包。

  4. 初始化Spring Context:使用AnnotationConfigApplicationContext加载配置类并初始化Spring Context。

示例注解配置

@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {@Beanpublic MyBean myBean(DependencyBean dependencyBean) {return new MyBean(dependencyBean);}@Beanpublic DependencyBean dependencyBean() {return new DependencyBean();}
}

初始化Context

ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MyBean myBean = context.getBean(MyBean.class);

通过这两种方式,可以定义Spring应用中的Beans,以及它们的依赖关系和配置。XML配置提供了声明式的配置方法,而注解配置则更加简洁且与Java代码紧密集成。随着Spring Boot的普及,注解配置方式越来越受到开发者的青睐。

BeanFactory和ApplicationContext的区别

在Spring框架中,BeanFactoryApplicationContext是控制反转(IoC)容器的两个核心接口。以下是这两个接口的功能对比和一些简单的源码示例来辅助说明它们之间的区别。

BeanFactory

BeanFactory 是Spring IoC容器的最基础形式,提供了依赖注入的基础设施。它主要负责实例化、配置和组装Beans。

public interface BeanFactory {Object getBean(String name) throws BeansException;<T> T getBean(String name, Class<T> requiredType) throws BeansException;boolean containsBean(String name);// ... 其他方法
}

使用场景示例(通常不会直接使用BeanFactory,而是使用其实现类):

BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
MyBean myBean = beanFactory.getBean(MyBean.class);

ApplicationContext

ApplicationContext 继承自BeanFactory,不仅包含了其所有功能,还提供了更多的高级功能,适用于企业级应用。

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,MessageSource, ApplicationEventPublisher, ResourcePatternResolver {// ... 继承自ListableBeanFactory等接口的方法// 发布事件void publishEvent(ApplicationEvent event);// 获取应用启动时间long getStartupDate();// ... 其他方法
}

使用场景示例:

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MyBean myBean = context.getBean(MyBean.class);
context.publishEvent(new CustomEvent());

区别

  1. 初始化方式
    BeanFactory 采用懒加载方式,即只有在第一次通过getBean获取Bean时才会创建和配置该Bean。
    ApplicationContext 采用急加载方式,容器启动时就创建所有非懒加载的Bean。

  2. 资源访问
    ApplicationContext 提供了对资源文件的访问能力,如通过getResourceAsStream方法。

  3. 事件机制
    只有ApplicationContext 支持事件发布和监听机制。

  4. 国际化
    只有ApplicationContext 支持国际化的MessageSource

  5. Web应用
    ApplicationContext 有专门针对Web应用的子接口,如WebApplicationContext

  6. 扩展性
    ApplicationContext 提供了更多的扩展点,如BeanFactoryPostProcessorBeanPostProcessor

  7. 使用场景
    对于简单应用或不需要Spring高级特性的应用,可以选择BeanFactory
    对于需要使用Spring高级特性的企业级应用,推荐使用ApplicationContext

在实际开发中,我们通常使用ApplicationContext的实现类来初始化Spring容器,如AnnotationConfigApplicationContextClassPathXmlApplicationContext,因为它们提供了更丰富的功能和更好的易用性。

Spring Context的生命周期

Spring Context的生命周期从容器的启动开始,一直到它的关闭。在这段时间内,Spring管理的Beans也会经历各自的生命周期。以下是Spring Context及其Bean生命周期的关键阶段,以及相应的代码说明:

1. 创建Spring Context

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

2. 注册配置类

context.register(SomeConfigClass.class);

3. 刷新容器(刷新是Spring Context生命周期的开始)

context.refresh();

刷新容器会触发以下操作:

  • 记录容器的开始创建时间。
  • 标记容器的活跃状态。
  • 初始化属性源、事件早期多播器等。
  • 获取BeanFactory,并检查是否存在自定义的BeanFactoryPostProcessor和BeanPostProcessor。
  • 注册几个特定的beans,如那些与生命周期管理相关的。
  • 初始化MessageSource,用于国际化等功能。
  • 初始化ApplicationEventMulticaster,用于事件发布和监听。

4. 获取BeanFactory

BeanFactory beanFactory = context.getBeanFactory();

5. BeanFactoryPostProcessor的执行

// 假设SomeBeanFactoryPostProcessor是自定义的BeanFactoryPostProcessor
context.addBeanFactoryPostProcessor(new SomeBeanFactoryPostProcessor());

6. BeanPostProcessor的执行

// 假设SomeBeanPostProcessor是自定义的BeanPostProcessor
context.addBeanPostProcessor(new SomeBeanPostProcessor());

7. 初始化Beans

  • 容器会按照定义的顺序创建和初始化所有的非懒加载的Bean。

8. Bean的初始化和生命周期回调

public class SomeBean implements InitializingBean, DisposableBean {public void afterPropertiesSet() {// Bean属性设置之后调用,由InitializingBean接口提供}public void destroy() {// Bean销毁之前调用,由DisposableBean接口提供}
}

9. 触发@PostConstruct注解的方法

public class SomeBean {@PostConstructpublic void initMethod() {// Bean初始化后调用}
}

10. 触发@PreDestroy注解的方法

public class SomeBean {@PreDestroypublic void cleanupMethod() {// Bean销毁前调用}
}

11. 使用Beans

SomeBean someBean = context.getBean(SomeBean.class);

12. 关闭容器

context.close();

关闭容器会触发以下操作:

  • 触发单例Bean的销毁。
  • 发布相应的上下文关闭事件。
  • 关闭用于国际化等功能的MessageSource。
  • 关闭其他自定义的资源。

Spring Context的生命周期从refresh()方法开始,到close()方法结束。在这段时间内,每个Bean都会经历从实例化、属性赋值、初始化到销毁的完整过程。理解并利用这些生命周期特征,可以更好地管理资源、执行自定义的初始化或销毁逻辑。

自定义BeanFactoryPostProcessor 和 BeanPostProcessor

在Spring中,自定义BeanFactoryPostProcessorBeanPostProcessor可以让你在容器的生命周期过程中的特定点执行自定义逻辑。以下是如何自定义这两种处理器的步骤和示例:

自定义 BeanFactoryPostProcessor

BeanFactoryPostProcessor接口允许你在容器实例化后、依赖注入之前修改Bean的定义信息。

  1. 实现接口:创建一个类实现BeanFactoryPostProcessor接口。
  2. 重写方法:重写postProcessBeanFactory方法。
  3. 注册处理器:将你的处理器添加到Spring上下文中。

示例

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {// 修改beanFactory中的bean定义信息// 例如,打印所有bean的名字String[] beanNames = beanFactory.getBeanDefinitionNames();for (String name : beanNames) {System.out.println(name);}}
}

在配置类中注册:

@Configuration
public class AppConfig {@Beanpublic MyBeanFactoryPostProcessor myBeanFactoryPostProcessor() {return new MyBeanFactoryPostProcessor();}
}

自定义 BeanPostProcessor

BeanPostProcessor接口允许你在容器初始化Bean的前后执行自定义逻辑。

  1. 实现接口:创建一个类实现BeanPostProcessor接口。
  2. 重写方法:重写postProcessBeforeInitializationpostProcessAfterInitialization方法。
  3. 注册处理器:将你的处理器添加到Spring上下文中。

示例

public class MyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("Before initialization of " + beanName);// 可以修改bean实例return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("After initialization of " + beanName);// 可以修改bean实例return bean;}
}

在配置类中注册:

@Configuration
public class AppConfig {@Beanpublic MyBeanPostProcessor myBeanPostProcessor() {return new MyBeanPostProcessor();}
}

使用 @Bean 标注的方法参数注入

在Spring 4.3+,你可以使用@Bean方法的参数来注入其他beans,实现更加精细的控制。

@Bean
public MyBeanPostProcessor myBeanPostProcessor(AnotherBean anotherBean) {return new MyBeanPostProcessor(anotherBean);
}

注意事项

  • BeanFactoryPostProcessor的优先级高于BeanPostProcessor,因此可以在Bean的属性设置之前修改Bean的定义。
  • BeanPostProcessor允许修改新创建的bean实例,可以在初始化前后执行逻辑。
  • 过度使用这些处理器可能会使代码逻辑变得复杂,因此应当谨慎使用。

通过自定义BeanFactoryPostProcessorBeanPostProcessor,可以在Spring容器的启动过程中插入自定义逻辑,增强了框架的灵活性和扩展性。

事件机制

Spring框架的事件机制允许在Spring容器中发布和监听不同的事件。以下是Spring事件机制的描述和如何使用ApplicationEventApplicationListener

1. 发布事件

在Spring中,任何继承自ApplicationEvent的类都可以作为一个事件被发布。

自定义事件

public class CustomEvent extends ApplicationEvent {private String message;public CustomEvent(Object source, String message) {super(source);this.message = message;}public String getMessage() {return message;}
}

发布事件

public class SomeComponent {@Autowiredprivate ApplicationEventPublisher publisher;public void someMethod() {// 发布一个自定义事件publisher.publishEvent(new CustomEvent(this, "Hello World!"));}
}

2. 监听事件

可以使用ApplicationListener接口或@EventListener注解来监听事件。

使用ApplicationListener接口

public class CustomEventListener implements ApplicationListener<CustomEvent> {@Overridepublic void onApplicationEvent(CustomEvent event) {System.out.println("Received custom event - " + event.getMessage());}
}

使用@EventListener注解

@Component
public class AnotherEventListener {@EventListenerpublic void onCustomEvent(CustomEvent event) {System.out.println("Received custom event with @EventListener - " + event.getMessage());}
}

3. 注册监听器

Spring会自动注册那些通过@Component@Service@Repository@Configuration注解的类作为监听器,只要它们实现了ApplicationListener接口或使用了@EventListener注解。

4. 异步监听

Spring还支持异步事件监听,只需在@EventListener注解中设置fallbackExecution属性即可。

@EventListener(fallbackExecution = "defaultOnCustomEventListener")
public void onCustomEvent(CustomEvent event) {// 异步处理事件
}public void defaultOnCustomEventListener(CustomEvent event) {// 默认方法,当异步处理失败时执行
}

5. 事件传播

事件可以在不同的层次(如父子容器)之间传播,子容器可以发布事件到父容器。

Spring的事件机制提供了一种在Spring容器内部组件之间进行通信的方法。通过发布和监听自定义事件,可以在Spring应用中实现复杂的业务逻辑和解耦。使用ApplicationEventApplicationListener可以轻松地创建和响应事件,而异步监听则提供了处理长时间运行操作的能力,从而不会阻塞主线程。

自定义事件和监听器

在Spring框架中,自定义事件和监听器主要涉及以下几个步骤:

1. 创建自定义事件类

自定义事件类通常继承自ApplicationEvent类。你可以在自定义事件类中添加额外的状态字段,以携带事件相关的信息。

示例

import org.springframework.context.ApplicationEvent;public class CustomEvent extends ApplicationEvent {private String info;public CustomEvent(Object source, String info) {super(source);this.info = info;}public String getInfo() {return info;}
}

2. 发布自定义事件

要在Spring应用中发布事件,你需要获取ApplicationEventPublisher的实例,并通过它来发布事件。

示例

import org.springframework.context.ApplicationEventPublisher;public class SomeComponent {@Autowiredprivate ApplicationEventPublisher publisher;public void someMethod() {// 发布一个自定义事件CustomEvent ce = new CustomEvent(this, "Some event info");publisher.publishEvent(ce);}
}

3. 创建事件监听器

事件监听器可以是任何Spring管理的Bean,它通过实现ApplicationListener接口或使用@EventListener注解来监听事件。

使用ApplicationListener接口

import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;@Component
public class CustomEventListener implements ApplicationListener<CustomEvent> {@Overridepublic void onApplicationEvent(CustomEvent event) {System.out.println("Received custom event - " + event.getInfo());}
}

使用@EventListener注解

import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;@Component
public class AnotherEventListener {@EventListenerpublic void onCustomEvent(CustomEvent event) {System.out.println("Received custom event with @EventListener - " + event.getInfo());}
}

4. 异步事件监听

Spring还支持异步事件监听,你可以在@EventListener注解中设置fallbackExecution属性来实现。

示例

@EventListener(fallbackExecution = "handleException")
public void handleCustomEvent(CustomEvent event) {// 异步处理事件
}public void handleException(CustomEvent event, Throwable ex) {// 异常处理
}

5. 注册事件监听器

在Spring中,事件监听器通常是Spring容器中的Bean。因此,你只需要用@Component@Service@Repository注解标注你的监听器类,Spring会自动注册它们。

6. 事件传播

在基于继承的Spring容器结构中,事件会在所有子容器中传播。如果需要,可以通过设置事件的propagation属性来控制这一行为。

通过创建自定义的事件类和监听器,可以在Spring应用中实现复杂的通信机制。事件机制为解耦合应用组件提供了一种有效的方式,同时异步事件监听增加了处理长时间运行操作的能力。自定义事件和监听器是Spring框架中实现事件驱动架构的重要工具。

资源访问机制

Spring框架提供了一套强大的资源访问机制,允许应用程序以统一的方式访问各种类型的资源,包括类路径资源、文件系统资源、Web资源等。以下是Spring资源访问机制的工作原理和关键组件的解释:

Resource 接口

Resource 接口是Spring资源访问机制的核心,它代表了低层次的资源访问抽象。Resource 接口提供了多种方法来访问和操作资源:

  • InputStream getInputStream(): 获取资源的输入流。
  • boolean exists(): 检查资源是否存在。
  • boolean isOpen(): 检查资源是否已打开。
  • URL getURL(): 获取资源的URL。
  • File getFile(): 获取资源的File对象。
  • String getDescription(): 获取资源的描述信息。

ResourceLoader 接口

ResourceLoader 接口用于加载资源,并为其他接口如BeanFactoryApplicationContext提供资源访问的能力。它定义了一个getResource方法,用于根据给定的资源位置返回Resource对象:

Resource getResource(String location);

ClassPathResource 和 FileSystemResource

Spring提供了多种Resource的实现类,用于访问不同类型的资源:

  • ClassPathResource: 用于访问类路径下的资源,如通过"classpath:example.properties"
  • FileSystemResource: 用于访问文件系统上的资源,如通过"file:/path/to/file.txt"

资源访问示例

以下是如何使用Spring资源访问机制的示例:

import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import java.io.IOException;public class ResourceExample {public void readClassPathResource() throws IOException {// 创建类路径资源Resource resource = new ClassPathResource("example.properties");// 读取资源内容String content = StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8);System.out.println(content);}public void readFileSystemResource() throws IOException {// 创建文件系统资源Resource resource = new FileSystemResource("/path/to/file.txt");// 读取资源内容String content = StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8);System.out.println(content);}
}

作用和优势

  • 解耦资源访问:通过ResourceResourceLoader接口,Spring将资源访问的实现细节抽象化,使得代码不依赖于具体的资源位置或类型。
  • 支持多种资源:Spring的资源机制支持多种资源类型,包括URL、文件、类路径资源等,提供了统一的访问方式。
  • 易于扩展:开发者可以根据需要实现自定义的ResourceResourceLoader,以支持访问特殊的资源。

Spring的资源访问机制为处理不同来源的资源提供了一种灵活和统一的方法,这在构建需要访问外部资源的应用时非常有用。

国际化

Spring框架的国际化功能主要依赖于MessageSource接口来实现。以下是Spring实现国际化的详细步骤和概念:

1. 理解国际化消息

在国际化应用程序中,消息通常不会硬编码为特定语言的字符串,而是使用消息代码来表示。这些代码可以在不同的属性文件中找到对应的翻译文本。

2. MessageSource接口

MessageSource接口是Spring框架中用于解析消息的关键组件。它允许你根据消息代码和可选的参数来检索国际化消息。

3. ResourceBundleMessageSource

Spring提供了ResourceBundleMessageSource实现,它使用Java的ResourceBundle来加载属性文件。这些属性文件包含了消息代码和对应语言的消息文本。

4. 创建属性文件

根据需要支持的语言,创建相应的属性文件。例如:

  • messages.properties:默认英文消息。
  • messages_fr.properties:法语消息。
  • messages_de.properties:德语消息。

5. 配置MessageSource

在Spring配置中,指定basename属性来加载基本的属性文件。如果有多个属性文件,可以使用逗号分隔的列表。

Java配置

@Bean
public MessageSource messageSource() {ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();messageSource.setBasenames("messages", "validation"); // 可以指定多个basenamemessageSource.setDefaultEncoding("UTF-8");return messageSource;
}

XML配置

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"><property name="basenames"><list><value>messages</value><value>validation</value></list></property><property name="defaultEncoding" value="UTF-8"/>
</bean>

6. 使用消息

在代码中,使用MessageSource来获取国际化消息。

@Autowired
private MessageSource messageSource;public String getLocalizedMessage(String code, Locale locale) {return messageSource.getMessage(code, null, locale);
}

7. 在视图模板中使用消息

在Thymeleaf、JSP或其他视图模板中,使用#{}语法来插入国际化消息。

Thymeleaf示例

<span th:text="#{home.welcome}">Welcome!</span>

8. 设置区域设置(Locale)

Spring将根据用户的区域设置来加载相应的消息。区域设置可以通过多种方式设置,包括用户偏好、HTTP请求头或配置。

Java代码中设置Locale

Locale locale = new Locale("fr", "FR");
messageSource.getMessage("home.welcome", null, locale);

在Web应用程序中根据请求设置Locale

LocaleResolver localeResolver = ...; // 由框架提供
Locale locale = localeResolver.resolveLocale(request);

9. 属性文件的热加载

对于开发期间,可以使用ReloadableResourceBundleMessageSource来实现属性文件的热加载,这样修改消息后不需要重启应用。

Spring的国际化支持允许创建多语言应用程序,而无需硬编码消息文本。通过使用MessageSource接口和属性文件,可以为不同的区域设置提供适当的消息。这使得应用程序能够适应全球化需求,为不同语言的用户提供本地化体验。

附加内容

深入理解Spring Context的源码,特别是AbstractApplicationContextDefaultListableBeanFactory,可以更好地掌握Spring框架的工作原理。以下是这两个类更详细的分析:

AbstractApplicationContext

AbstractApplicationContext是Spring中所有具体应用上下文实现的基类,它实现了ApplicationContext接口,提供了应用上下文的通用行为和生命周期管理。

关键组件和流程

  1. 生命周期管理

    • refresh():刷新容器,初始化属性源、事件早期多播器、MessageSource、ApplicationEventMulticaster等。
    • registerShutdownHook():注册关闭钩子,以确保应用关闭时能优雅地释放资源。
  2. 获取BeanFactory

    • obtainFreshBeanFactory():获取一个新的DefaultListableBeanFactory实例,这是实际管理Bean生命周期的地方。
  3. BeanFactoryPostProcessor和BeanPostProcessor的注册

    • 允许开发者通过这些处理器在容器启动时自定义或修改Bean的定义和行为。
  4. 事件发布

    • publishEvent():发布应用事件,可以用于在组件之间进行通信。
  5. 资源访问

    • 提供了访问资源文件的方法,如getResourceAsStream()
  6. MessageSource

    • 用于国际化等功能,允许根据区域设置获取本地化消息。

DefaultListableBeanFactory

DefaultListableBeanFactory是Spring中用于管理Bean生命周期的核心工厂类,它实现了ListableBeanFactory接口。

关键特性和方法

  1. Bean定义

    • registerBeanDefinition():注册一个Bean的定义,可以是全限定类名、BeanDefinition对象或@Bean注解的方法。
  2. 依赖注入

    • autowireBeanProperties():自动装配Bean的属性,处理@Autowired注解。
  3. Bean生命周期

    • getBean():获取Bean实例,触发Bean的创建、属性设置、初始化和销毁。
    • initializeBean():初始化Bean,应用@PostConstruct注解的方法。
    • destroyBean():销毁Bean,应用@PreDestroy注解的方法。
  4. 扩展点

    • 提供了多个扩展点,如BeanFactoryPostProcessorBeanPostProcessorInstantiationAwareBeanPostProcessor等,允许开发者在不同阶段介入Bean的创建和管理。
  5. 类型转换

    • convertIfNecessary():进行类型转换,支持Spring的@Value注解。
  6. Bean创建过程

    • createBeanInstance():创建Bean实例。
    • populateBean():设置Bean属性。
    • initializeBean():初始化Bean。

通过深入理解Spring Context的工作原理和源码实现,我们不仅能够更加灵活地使用Spring框架构建企业级应用,还可以根据项目需求进行定制和扩展。从基础的IoC容器到复杂的事件驱动系统,Spring Context展示了其作为Spring心脏的强大功能。

这篇关于【Spring】8.深入探索Spring Context:由浅入深直击Spring的心脏的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/959622

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于