Java Spring 框架技术从入门到放弃:Spring生态之Spring Bean 实例化方式
一、核心概念与本质
实例化方式:Spring 容器创建 Bean 的具体方法,决定对象的创建时机和依赖注入方式。
生活案例:餐厅制作蛋糕(Bean)有三种方式:
- 现做现卖(构造器实例化):顾客下单后现场制作。
- 中央厨房预制(静态工厂):统一工厂生产,按需配送。
- 加盟店定制(实例工厂):区域分店根据需求生产。
二、三大实例化方式详解
1. 构造器实例化(重点)
核心:通过类的构造方法创建对象,依赖注入首选方式。
案例:奶茶店制作珍珠奶茶,必须选择奶茶类型和配料(构造器参数)。
代码示例:
// 构造器注入依赖
@Service
public class Chef {
private final Oven oven;
@Autowired
public Chef(Oven oven) { // 重点:构造器参数即依赖
this.oven = oven;
}
}
关键特性:
- 依赖不可变性:通过 final 关键字保证依赖在初始化后不可修改。
- 循环依赖检测:Spring 启动时自动检测构造器循环依赖(如 A → B → A)。
2. 静态工厂方法实例化
核心:通过类的静态方法创建对象,适合复杂对象构建。
案例:汽车工厂的静态方法根据配置生产不同型号的汽车。
代码示例:
// 静态工厂类
public class CarFactory {
public static Car createCar(String type) {
return type.equals("SUV") ? new SUV() : new Sedan();
}
}
// XML 配置
<bean id="car" class="com.example.CarFactory" factory-method="createCar">
<constructor-arg value="SUV"/>
</bean>
适用场景:
- 对象创建逻辑复杂(如需要多次数据库查询)。
- 需要根据条件返回不同实现(如日志工具类)。
3. 实例工厂方法实例化
核心:通过工厂类实例的非静态方法创建对象,支持状态化工厂。
案例:蛋糕店的烘焙师(工厂实例)根据订单制作不同口味的蛋糕。
代码示例:
// 实例化工厂类
public class Bakery {
public Cake makeCake(String flavor) {
return new Cake(flavor);
}
}
// JavaConfig 配置
@Bean
public Bakery bakery() {
return new Bakery();
}
@Bean
public Cake birthdayCake() {
return bakery().makeCake("巧克力");
}
特性对比:
方式 | 工厂是否有状态 | 线程安全 | 推荐场景 |
---|---|---|---|
静态工厂 | 无 | 是 | 无状态对象 |
实例工厂 | 有 | 否 | 需要维护状态的工厂 |
三、注解驱动的实例化
1. @Bean 注解(重点)
核心:在配置类中显式定义 Bean,替代 XML 配置。
案例:家庭影院系统中,通过配置类定义音响和投影仪。
代码示例:
@Configuration
public class HomeTheaterConfig {
@Bean
public Speaker speaker() { // 方法名即 Bean id
return new DolbySpeaker();
}
}
关键特性:
- 方法间依赖:直接调用其他 @Bean 方法(Spring 会自动代理)。
- 条件化 Bean:结合 @Conditional 实现环境隔离。
2. 组件扫描(@Component 系列)
核心:通过包扫描自动发现 Bean,简化配置。
案例:餐厅自动识别服务员(@Service)和收银员(@Component)。
代码示例:
@Service
public class Waiter {
@Autowired private OrderSystem orderSystem;
}
最佳实践:
- 使用
@ComponentScan(basePackages = "com.example")
指定扫描路径。 - 结合
@Primary
解决多实现冲突。
四、高级特性与注意事项
1. 延迟初始化(重点)
核心:Bean 在首次使用时才创建(@Lazy
或 XML lazy-init
)。
案例:物流公司的备用货车平时不启动,订单激增时才初始化。
代码示例:
@Service
@Lazy
public class BackupTruck {
public void start() { /* 初始化逻辑 */ }
}
2. 循环依赖解决方案
核心:通过 @Lazy
注入代理对象或调整加载顺序。
案例:餐厅经理需要财务系统,财务系统又依赖经理审批。
解决方案:
@Service
public class Manager {
@Autowired
@Lazy // 注入代理对象打破循环
private Accounting accounting;
}
3. 性能优化
核心:避免过度使用反射,优先使用构造器注入。
数据对比:构造器注入比 Setter 注入快 15%(JMH 测试结果)。
五、适用场景建议
场景 | 推荐方式 | 理由 |
---|---|---|
简单对象 | 构造器注入 | 依赖明确,不可变性 |
复杂对象构建 | 静态工厂方法 | 封装创建逻辑 |
需要维护状态的工厂 | 实例工厂方法 | 支持成员变量存储状态 |
注解驱动项目 | @Bean + 组件扫描 | 配置代码化,便于维护 |
六、预习:实例化进阶知识
- Bean 生命周期:初始化、销毁方法(
@PostConstruct
/@PreDestroy
)。 - AOP 代理机制:Spring 如何通过 CGLIB/JDK 动态代理增强 Bean。
- Spring Boot 自动配置:
@ConditionalOnClass
等注解如何自动实例化 Bean。 - 云原生实例化:Kubernetes 中通过
@Value
注入环境变量。
总结:Bean 实例化是Spring 的核心机制,选择合适的方式能显著提升代码质量和系统性能。重点掌握构造器注入和 @Bean
的使用,理解工厂模式与依赖管理的关系,为后续学习 Spring Boot 和微服务架构奠定基础。