@Configuration是否为单例?@Configuration与@Component选哪个实现单例?
嘿,这个问题确实挺容易搞混的,我来帮你梳理清楚!
首先划个重点:不管是@Configuration还是@Component,默认情况下它们标注的类都会被Spring创建为单例Bean——这是Spring容器的默认行为,和注解本身的核心职责没有直接绑定(你要是想改多例,加个@Scope("prototype")就行)。
那两者的区别在哪里,什么时候该用哪个?往下看:
1. @Component:标记普通Bean的基础注解
它是Spring最基础的 stereotype 注解,核心作用就是告诉Spring:“把这个类纳入容器管理吧”。常见的@Service、@Repository、@Controller其实都是它的派生注解,只是语义更明确。
比如你有个工具类或者业务服务类,只想让Spring帮你管理成单例,直接用@Component就够了:
@Component public class OrderUtils { // 工具方法... }
这种情况下,Spring会自动扫描并创建这个类的单例实例,整个容器里只有这一个对象。
2. @Configuration:专门的配置类注解
@Configuration本质上也是@Component的派生类,所以它标注的类本身也会被Spring当作单例Bean管理,但它的核心职责是定义Bean的创建逻辑——也就是配合@Bean注解,手动声明那些没法用@Component扫描的Bean(比如第三方库的类)。
它最特殊的地方是:被@Configuration标注的类会被Spring生成一个CGLIB代理类。这样当你在配置类的@Bean方法里调用另一个@Bean方法时,Spring会确保返回的是容器里的单例Bean,而不是每次调用都新建对象。举个例子:
@Configuration public class AppConfig { @Bean public UserService userService() { // 这里调用userRepository(),返回的是容器里的单例实例 return new UserService(userRepository()); } @Bean public UserRepository userRepository() { return new UserRepository(); } }
如果把上面的@Configuration换成@Component,那userService()里调用userRepository()就会每次创建一个新的UserRepository对象,而不是复用容器里的单例——因为@Component标注的类不会被代理,@Bean方法就是普通的方法调用。
回到你的问题:该用哪个实现单例?
- 如果你的需求只是把一个普通类交给Spring管理成单例,用
@Component(或者它的派生注解)就完全足够了,这也是它的本职工作。 - 如果你的需求是定义Bean的创建逻辑,尤其是多个Bean之间有依赖关系,那才需要用
@Configuration,它的单例特性只是附带的,核心价值是保证内部@Bean方法调用的单例性。
内容的提问来源于stack exchange,提问作者Jose Miguel

