【Spring】@configuration与@Bean底层详解
·
Spring中@Configuration与@Bean底层原理详解
在 Spring / Spring Boot 项目中,我们经常会写这样的代码:
@Configuration
public class RestConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
很多初学者都会有一个疑问:
@Bean 方法是不是每次注入都会执行一次?
@Autowired 注入的是不是新对象?
本文带你彻底搞清楚。
一、Spring 容器是如何处理 @Configuration 的?
1️⃣ 启动流程
Spring 启动时会:
- 扫描带有
@Configuration的类 - 解析其中的
@Bean方法 - 执行
@Bean方法 - 将返回值注册进 IoC 容器
简化理解如下:
public class SpringContainer {
private Map<String, Object> singletonObjects = new HashMap<>();
public void initialize() {
RestConfig config = new RestConfig();
Object bean = config.restTemplate(); // 执行一次
singletonObjects.put("restTemplate", bean);
}
public Object getBean(String name) {
return singletonObjects.get(name);
}
}
二、默认是单例模式(非常重要)
Spring Bean 默认作用域:
singleton(单例)
示例:
@Service
public class OrderService {
@Autowired
private RestTemplate restTemplate1;
@Autowired
private RestTemplate restTemplate2;
public void test() {
System.out.println(restTemplate1 == restTemplate2);
}
}
输出:
true
说明:
注入的是同一个 Bean 实例。
三、如何验证 @Bean 只执行一次?
@Configuration
public class RestConfig {
private int counter = 0;
@Bean
public RestTemplate restTemplate() {
counter++;
System.out.println("创建次数:" + counter);
return new RestTemplate();
}
}
启动时只会输出一次:
创建次数:1
四、生命周期流程图
Spring启动
↓
扫描@Configuration
↓
执行@Bean方法
↓
放入单例池
↓
@Autowired 从容器获取
五、如果想每次获取都是新对象?
使用 prototype 作用域:
@Bean
@Scope("prototype")
public RestTemplate restTemplate() {
return new RestTemplate();
}
验证:
@Autowired
private ApplicationContext context;
public void test() {
RestTemplate r1 = context.getBean(RestTemplate.class);
RestTemplate r2 = context.getBean(RestTemplate.class);
System.out.println(r1 == r2);
}
输出:
false
六、@Configuration 的 CGLIB 代理机制(进阶)
如果你在配置类中调用另一个 @Bean 方法:
@Bean
public A a() {
return new A(b());
}
@Bean
public B b() {
return new B();
}
Spring 会通过 CGLIB 代理增强配置类,保证:
即使在内部方法调用,也不会重复创建 Bean。
七、总结
✅ @Bean 方法默认只执行一次
✅ 默认作用域是 singleton
✅ @Autowired 获取的是容器中的对象
✅ prototype 需要显式声明
✅ @Configuration 会被 CGLIB 增强
更多推荐



所有评论(0)