spring-context 是 Spring 框架的核心模块之一,它建立在 Spring Core 基础之上,提供了 IoC 容器的高级实现 和企业级服务集成。
一、核心组件
1. ApplicationContext(应用上下文)
是 BeanFactory 的扩展,提供更丰富的功能:
java
// 主要实现类
- AnnotationConfigApplicationContext // 注解配置
- ClassPathXmlApplicationContext // XML配置
- FileSystemXmlApplicationContext // 文件系统XML
- GenericWebApplicationContext // Web环境
2. 核心功能差异
java
BeanFactory (基础容器) ApplicationContext (高级容器)
- 懒加载单例 - 预实例化单例
- 基础DI支持 - 完整AOP集成
- 无国际化 - 国际化(i18n)
- 无事件机制 - 事件发布/监听
- 无自动配置 - 自动配置支持
二、生命周期管理
java
// Bean的生命周期回调
@Component
public class MyBean implements InitializingBean, DisposableBean {
@PostConstruct
public void init() { /* 初始化 */ }
@PreDestroy
public void destroy() { /* 销毁 */ }
}
// 容器生命周期
AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
context.registerShutdownHook(); // 注册JVM关闭钩子
context.start(); // 启动生命周期
context.stop(); // 停止生命周期
context.close(); // 关闭容器
三、事件机制
java
// 1. 定义事件
public class MyEvent extends ApplicationEvent {
private String message;
public MyEvent(Object source, String message) {
super(source);
this.message = message;
}
}
// 2. 发布事件
@Component
public class EventPublisher {
@Autowired
private ApplicationEventPublisher publisher;
public void publish(String msg) {
publisher.publishEvent(new MyEvent(this, msg));
}
}
// 3. 监听事件
@Component
public class MyListener {
@EventListener
public void handleMyEvent(MyEvent event) {
System.out.println("收到事件: " + event.getMessage());
}
// 条件监听
@EventListener(condition = "#event.message.contains('urgent')")
public void handleUrgent(MyEvent event) { }
}
四、国际化支持
html
<!-- messages_zh_CN.properties -->
greeting=你好 {0}
farewell=再见
<!-- messages_en_US.properties -->
greeting=Hello {0}
farewell=Goodbye
java
@Configuration
public class I18nConfig {
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource ms = new ResourceBundleMessageSource();
ms.setBasename("messages");
ms.setDefaultEncoding("UTF-8");
ms.setCacheSeconds(3600);
return ms;
}
}
// 使用
@Component
public class I18nService {
@Autowired
private MessageSource messageSource;
public void greet(String name, Locale locale) {
String msg = messageSource.getMessage("greeting",
new Object[]{name},
locale);
System.out.println(msg);
}
}
五、资源加载
java
// ResourceLoader 统一资源访问
@Component
public class ResourceService {
@Autowired
private ResourceLoader resourceLoader;
public void loadResource() throws IOException {
// 类路径资源
Resource res1 = resourceLoader.getResource("classpath:config.xml");
// 文件系统资源
Resource res2 = resourceLoader.getResource("file:/data/config.xml");
// URL资源
Resource res3 = resourceLoader.getResource("https://example.com/data.json");
// 读取内容
String content = new String(res1.getInputStream().readAllBytes());
}
}
六、配置方式对比
| 特性 | XML配置 | 注解配置 | Java Config |
|---|---|---|---|
| 声明方式 | <bean> |
@Component |
@Bean |
| 依赖注入 | <property> |
@Autowired |
方法调用 |
| 作用域 | scope |
@Scope |
@Scope |
| 懒加载 | lazy-init |
@Lazy |
@Lazy |
| 条件化 | SpEL | @Conditional |
@Conditional |
java
// Java Config 示例
@Configuration
@ComponentScan("com.example")
@PropertySource("classpath:app.properties")
@Import(DatabaseConfig.class)
public class AppConfig {
@Value("${app.name}")
private String appName;
@Bean
@Scope("singleton")
public MyService myService() {
return new MyService(appName);
}
@Bean
@Conditional(DevCondition.class)
public DevService devService() {
return new DevService();
}
}
七、作用域管理
java
// 1. 标准作用域
@Component
@Scope("singleton") // 默认,单例
public class SingletonBean { }
@Component
@Scope("prototype") // 原型,每次新实例
public class PrototypeBean { }
// 2. Web作用域(需要web环境)
@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestBean { }
@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class SessionBean { }
// 3. 自定义作用域
@Component
public class CustomScope implements Scope {
private Map<String, Object> cache = new ConcurrentHashMap<>();
@Override
public Object get(String name, ObjectFactory<?> factory) {
return cache.computeIfAbsent(name, k -> factory.getObject());
}
// 其他方法实现...
}
@Configuration
public class ScopeConfig {
@Bean
public CustomScope customScope() {
return new CustomScope();
}
@Bean
public CustomScopeConfigurer customScopeConfigurer() {
CustomScopeConfigurer configurer = new CustomScopeConfigurer();
configurer.addScope("custom", customScope());
return configurer;
}
}
八、环境抽象
java
// Environment 统一管理配置
@Service
public class EnvService {
@Autowired
private Environment env;
public void showProfiles() {
// 获取激活的profile
String[] profiles = env.getActiveProfiles();
// 获取属性值
String dbUrl = env.getProperty("database.url");
Integer port = env.getProperty("server.port", Integer.class, 8080);
// 判断profile
boolean isDev = env.acceptsProfiles(Profiles.of("dev"));
}
// 设置profile
// JVM参数: -Dspring.profiles.active=dev,local
// 代码设置: context.getEnvironment().setActiveProfiles("prod");
}
九、常见应用场景
java
// 1. 多配置文件组合
@Configuration
@ImportResource("classpath:legacy-config.xml") // 导入XML配置
public class MainConfig {
@Import(DatabaseConfig.class, SecurityConfig.class) // 导入其他配置类
}
// 2. 延迟初始化
@Component
@Lazy(true)
public class LazyBean {
public LazyBean() {
System.out.println("只在第一次使用时创建");
}
}
// 3. FactoryBean 模式
@Component
public class MyFactoryBean implements FactoryBean<Product> {
@Override
public Product getObject() {
return new ComplexProduct();
}
@Override
public Class<?> getObjectType() {
return Product.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
十、性能优化建议
java
// 1. 使用索引加速启动
// META-INF/spring.components 文件(自动生成)
// 2. 懒加载非核心Bean
@Component
@Lazy
public class HeavyBean { }
// 3. 条件化注册
@Bean
@ConditionalOnClass(name = "com.mysql.jdbc.Driver")
public DataSource mysqlDataSource() { }
// 4. 避免循环依赖
// 构造器注入 > Setter注入 > 字段注入
@Service
public class ServiceA {
private final ServiceB serviceB;
public ServiceA(ServiceB serviceB) { // 构造器注入
this.serviceB = serviceB;
}
}
总结 :spring-context 提供了完整的企业级应用容器,核心是 ApplicationContext,它整合了 IoC、AOP、事件、国际化、资源管理等能力,是 Spring Framework 的心脏。