文章目录
如何理解上下文
上下文是一个抽象的概念,通常指的是某个特定时刻或某个特定环境下的状态和条件。上下文可以包含各种信息(如变量、数据、状态、环境设置等),这些信息共同决定了程序或系统在当前时刻的行为。
1、在 Web 开发中,上下文通常包含了请求、会话、应用配置等信息,这些信息共同决定了程序的行为。
2、在 Spring 框架中,上下文的概念被进一步细化:
- 请求上下文(Request Context):指处理单个 HTTP 请求时的环境。它包含了请求的所有信息,如请求头、请求参数、会话信息等。
- 应用上下文(Application Context):指整个 Web 应用程序的环境。它包含了应用程序的所有配置信息、Bean定义、依赖注入等。
- 线程上下文(Thread Context):指当前线程的环境。在多线程环境中,每个线程都有自己的上下文,包括线程局部变量、线程状态等。
Spring 的应用上下文
先看一段代码:
@Component
public final class SpringUtil implements BeanFactoryPostProcessor, ApplicationContextAware {
private static ConfigurableListableBeanFactory beanFactory;
private static ApplicationContext applicationContext;
// 获取 并 赋值保存 配置列表工厂 的实例
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {
beanFactory = factory;
}
// 获取 并 赋值保存 应用上下文 的实例
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
SpringUtil.applicationContext = context;
}
}
这段代码主要用于在 spring 应用上下文启动时,获取并保存 应用上下文、配置列表工厂 的实例。
1、BeanFactoryPostProcessor
接口:实现该接口,需要重写 postProcessBeanFactory
方法。该接口用于在 Spring 容器实例化任何 bean 之前,对 ConfigurableListBeanFactory
进行修改。ConfigurableListBeanFactory
是 spring 中用于 访问和操作 bean 定义、bean实例 的接口。
怎么修改?----> 就是在重写的 postProcessBeanFactory
方法里:
@Component
public class Test implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
//1、获取并修改名为 myBean 的 bean 的定义:
// 获取定义
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("myBean");
// 修改定义
beanDefinition.getPropertyValues().add("property", "newValue");
//===========================================================
//2、添加或删除bean:
// 添加bean:其中MyBean就是myBean对象的类
BeanDefinition beanDefinition = new RootBeanDefinition(MyBean.class);
beanFactory.registerBeanDefinition("newBean", beanDefinition);
//删除bean
beanFactory.removeBeanDefinition("oldBean");
//===========================================================
//3、自定义bean的初始化逻辑:
// 先获取bean的定义
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("myBean");
// 修改bean的定义,添加初始化方法:这样,当Spring容器实例化 myBean 时,就会调用customInit 方法进行初始化(确保 MyBean 中有这个方法)
beanDefinition.setInitMethodName("customInit");
}
}
使用场景:
-
修改bean的定义:在Spring容器实例化bean之前,可以修改bean的定义,例如修改bean的属性值、添加或删除bean的依赖等。
-
添加或删除bean:在Spring容器实例化bean之前,可以添加或删除bean,例如根据某些条件动态添加或删除bean。
-
自定义bean的初始化逻辑:在Spring容器实例化bean之前,可以自定义bean的初始化逻辑,例如在bean的初始化方法之前执行一些额外的操作。
2、ApplicationContextAware
接口:实现该接口,需要重写 setApplicationContext
方法。该接口用于将 Spring 容器中的 ApplicationContext
实例注入到实现了该接口的类中。ApplicationContext
是 Spring 中用于 访问应用上下文和bean 的接口。
怎么注入?----> 就是在重写的 setApplicationContext
方法里,这个方法会在 Spring 容器初始化过程中被调用,并将 ApplicationContext
的实例注入到实现了该接口的类中。
使用场景:
-
获取bean实例:在Spring容器初始化过程中,可以通过
ApplicationContext
获取 bean 的实例。 -
获取应用上下文信息:可以通过
ApplicationContext
获取应用上下文的信息,例如获取应用上下文的ID、获取应用上下文的父上下文等。 -
发布事件:可以通过
ApplicationContext
发布事件,例如在某个操作完成后发布一个事件,其他实现了ApplicationListener
接口的类可以监听这个事件并进行相应的处理。
@Component
public class Test implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//1、获取bean实例
MyBean myBean = applicationContext.getBean(MyBean.class);
// 使用bean实例
myBean.doSomething();
//2、获取应用上下文信息
String contextId = applicationContext.getId();
ApplicationContext parentContext = applicationContext.getParent();
// 使用应用上下文信息
System.out.println("Context ID: " + contextId);
System.out.println("Parent Context: " + parentContext);
//3、发布事件:这样,当 Spring 容器初始化 Test 时,就会将 ApplicationContext 实例注入到 Test 中,并调用 setApplicationContext 方法。同时,其他实现了ApplicationListener 接口的类可以监听这个事件并进行相应的处理。
applicationContext.publishEvent(new MyEvent("Hello, World!"));
}
}
上面 3 个场景:当 Spring 容器初始化
Test
时,就会将ApplicationContext
实例注入到Test
中,并调用setApplicationContext
方法