1. Bean的作用域深度解析
在Spring框架中,Bean的作用域决定了Bean实例的创建方式和生命周期。理解作用域对于构建正确的Spring应用至关重要,特别是在多线程环境和Web应用中。
1.1 单例作用域(singleton)的实战考量
单例模式是Spring默认的作用域,也是使用最广泛的一种。在实际项目中,我遇到过不少因为错误使用单例导致的线程安全问题。比如:
java复制@Component
public class CounterService {
private int count = 0;
public void increment() {
count++;
}
public int getCount() {
return count;
}
}
这个简单的计数器在多线程环境下会出现竞态条件。解决方法通常有:
- 使用synchronized关键字
- 改为原型作用域(prototype)
- 使用ThreadLocal变量
重要提示:单例Bean中要特别注意成员变量的线程安全性。无状态Bean(没有成员变量或只有final成员变量)是最安全的单例实现方式。
1.2 原型作用域(prototype)的应用场景
原型作用域每次都会创建新实例,适合以下场景:
- 需要维护独立状态的Bean
- 高代价对象(如数据库连接)通常不适合
- 需要避免线程安全问题的场景
在Spring MVC中,控制器默认是单例的。如果控制器需要维护状态,可以这样配置:
java复制@Controller
@Scope("prototype")
public class UserController {
// 控制器逻辑
}
1.3 Web相关作用域的注意事项
对于request、session、application和websocket作用域,有几个关键点需要注意:
- 必须注册RequestContextListener或使用RequestContextFilter
- 代理模式的选择:
java复制@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS) public UserPreferences userPreferences() { return new UserPreferences(); } - 在非Web环境中使用这些作用域会抛出异常
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Bean生命周期的完整解读
理解Bean的生命周期对于编写高质量的Spring应用至关重要。下面我将结合自己多年的实践经验,详细解析每个阶段。
2.1 实例化阶段的底层机制
Spring通过反射调用构造方法创建Bean实例。这里有几个常见问题:
- 构造方法注入的循环依赖问题
- 当有多个构造方法时,Spring的选择策略
- 使用Objenesis绕过构造方法(用于某些特殊场景)
一个典型的构造方法注入示例:
java复制@Service
public class OrderService {
private final UserService userService;
public OrderService(UserService userService) {
this.userService = userService;
}
}
2.2 属性赋值的各种方式
Spring提供了多种依赖注入方式:
| 注入方式 | 示例 | 适用场景 |
|---|---|---|
| 构造器注入 | 如上例 | 强依赖,推荐方式 |
