news 2026/4/18 8:47:14

@Configuration(Spring)详解让你懂它是什么、怎么用、常见坑与面试点

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
@Configuration(Spring)详解让你懂它是什么、怎么用、常见坑与面试点

总结:
@Configuration用来定义Java 配置类,用@Bean方法声明 Spring 管理的 Bean;Spring 会把它当作配置信息并用 CGLIB 动态代理(默认)处理,从而保证@Bean方法的单例语义与依赖注入正确。

下面分条讲清楚你必须掌握的点(配合例子和常见面试问答)。


1. 基本用法(最常见的场景)

@Configuration public class AppConfig { @Bean public UserService userService() { return new UserService(userRepository()); } @Bean public UserRepository userRepository() { return new UserRepository(); } }
  • AppConfig放到 Spring 上下文中(例如通过@SpringBootApplication的组件扫描,或手工AnnotationConfigApplicationContext(AppConfig.class)),Spring 会解析@Bean并注册对应的 Bean。
  • 默认@Bean的作用域是singleton

2.@Configuration@Component的区别

  • @Configuration本身带有@Component(因此可以被扫描),但它的语义比普通@Component更强:
  • @Configuration类会被 Spring 用 CGLIB 生成子类(代理),以保证同一配置类中@Bean方法相互调用时仍然返回容器管理的单例实例。
  • 如果你用@Component+@Bean(理论上也能),则不会有 proxy 的增强语义,互相调用会直接执行方法(可能导致重复实例化)。

3. 关键属性:proxyBeanMethods(Spring 5.2+)

@Configuration(proxyBeanMethods = true)默认(会生成代理,保证@Bean调用返回容器里同一个 bean)。
如果你把它设置为false,Spring 不会对配置类做 CGLIB 代理,性能更好但失去方法间调用的单例保证,适合配置类只是用作“工厂”且不同@Bean之间互不调用的场景(常见于 Spring Boot 的自动配置优化)。

示例说明差异:

@Configuration(proxyBeanMethods = true) // 或 false public class Config { @Bean public A a() { return new A(b()); } @Bean public B b() { return new B(); } }
  • proxyBeanMethods = truea()内部调用b()实际会走代理,返回容器中的B单例。
  • proxyBeanMethods = falsea()直接调用b()方法,返回的是新创建的 B 实例,会破坏单例语义。

4. 为什么需要 CGLIB 代理?(简要原理)

  • Spring 在解析@Configuration时,会把该类变成一个代理子类(CGLIB),当在配置类内调用b()时,调用会被拦截,代理去容器中取B(如果已存在),而不是直接在方法体内 new 一个新对象。
  • 因此不要把@Configuration类声明为final(CGLIB 需要继承)。

5. 常用组合与扩展

  • @Configuration常和以下注解一起使用:
    • @Bean:声明一个 bean。
    • @Import:引入其他配置类或配置组件。
    • @Profile:按环境条件激活配置。
    • @PropertySource:加载属性文件(但在 Spring Boot 中通常使用application.properties/yml)。
    • @Enable*(例如@EnableTransactionManagement)用于开启某些功能。
  • @ConfigurationProperties@Configuration不同:前者用于绑定配置属性。

6. Bean 生命周期与依赖注入风格

  • @Bean方法内部可以用构造器或者 setter 来注入依赖(示例里用 new 时手动传入)。
  • 也可以在@Bean方法参数中声明需要注入的其他 bean,Spring 会自动注入(更推荐):
@Bean public UserService userService(UserRepository repo) { return new UserService(repo); }

此方式可避免proxyBeanMethods的问题(因为注入在容器层面已完成)。


7. 常见坑 & 注意事项

  1. 不要把@Configuration类标记为final— CGLIB 代理需要继承。
  2. 如果@Configuration(proxyBeanMethods=false),切忌在同一类中互相调用@Bean方法(会创建多个实例)。
  3. 如果你只是把配置类当作“静态工厂”,并且@Bean互不依赖,可以用proxyBeanMethods=false提升性能(Spring Boot 的自动配置大量使用该优化)。
  4. @Configuration会被ConfigurationClassPostProcessor处理,发生在常规 bean 定义之前。
  5. 如果忘记导入配置类到上下文,@Bean不会生效(需要 component-scan、@Import 或在 ApplicationContext 注册)。
  6. @Bean方法不要写为private(Spring 需要能调用/代理)。

8. 面试常考简短问答(可背)

  • Q:@Configuration的作用?
    A: 声明 Java 配置类,里面用@Bean注册 Spring Bean;Spring 会对该类进行特殊处理(默认 proxyBeanMethods=true)。
  • Q:@Configuration@Component有什么不同?
    A:@Configuration会被 Spring 作为配置并生成代理以保证@Bean方法互调仍返回容器的唯一 Bean;@Component没有这些语义。
  • Q: 什么是proxyBeanMethods
    A: 控制是否对配置类做CGLIB 代理true(默认):保证方法间互调返回容器中的单例;false:不代理,性能更好但会失去方法调度保障。
  • Q:@Configuration类可以是final吗?
    A: 不应是final,因为默认是通过子类代理(CGLIB)。

9. 完整 runnable 示例(演示 proxyBeanMethods 的差异)

@Configuration(proxyBeanMethods = true) // 改成 false 看对比 public class DemoConfig { @Bean public ServiceA serviceA() { System.out.println("create ServiceA"); return new ServiceA(serviceB()); } @Bean public ServiceB serviceB() { System.out.println("create ServiceB"); return new ServiceB(); } } public class ServiceA { private final ServiceB b; public ServiceA(ServiceB b) { this.b = b; } } public class ServiceB { }
  • 启动AnnotationConfigApplicationContext(DemoConfig.class)
  • proxyBeanMethods = true:输出通常只会看到create ServiceB一次,ServiceB为单例。
  • proxyBeanMethods = false:可能会看到create ServiceB两次(serviceA()内部直接 new 的ServiceB与容器注册的ServiceB),造成重复实例。

10. 什么时候用@Configuration而不是 XML / 注解扫描?

  • 推荐在现代 Spring / Spring Boot 项目中使用@Configuration(类型安全、可重构、IDE 支持好)。XML 仅在需要兼容老系统或某些特殊场景时使用。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/7 0:39:06

下雪天怎么上班?用UU远程高效居家办公

近期,北方多地受大雪天气影响,有的家门被封、有的交通堵塞! 寒冷天气陆地变滑,打工人的通勤路简直难上加难。但雪休可望而不可即,年终手头工作项目刻不容缓。 不想冒雪出门上班?不想大雪天被困在通勤路上&…

作者头像 李华
网站建设 2026/4/18 8:03:47

第五十六篇|AIM奈良国际学院的数据建模:古都城市学习节律与制度型语言学校的结构边界

第五十六篇|AIM奈良国际学院的数据建模:古都城市学习节律与制度型语言学校的结构边界 系列延续:日本语言学校结构数据工程 关键词:AIM奈良国际学院、奈良留学、教育数据建模、语言学校制度、学习节律、结构化字段、语校网 一、问题…

作者头像 李华
网站建设 2026/4/18 3:33:50

04.机器学习中的线性代数?

什么是机器学习中的线性代数? 在机器学习 (ML) 中,线性代数涉及使用数学运算来表示和操作 ML 模型内的数据、参数和运算。它提供语言和工具来表达数据在模型中的流动方式以及模型的“学习”方式。 强大的现代机器学习和生成式 AI 的核心是由线性代数驱动的。无论是训练神经网…

作者头像 李华
网站建设 2026/3/15 14:23:00

混合开发模式是救星还是坑?3个案例揭秘节省40万成本的秘诀

亲爱的小伙伴们,今天咱们来聊一个让无数企业又爱又恨的话题——混合开发模式!💻🚀 你是不是也经常听到“混合开发能省40万成本”的说法,心里直犯嘀咕:这到底是真香警告,还是隐藏的深坑&#xff…

作者头像 李华
网站建设 2026/4/8 21:52:57

让创业更有后劲,长沙用金融铺就“成长跑道”

近几年,关于年轻人创业的讨论很多,但按照一线创业人提供的经验来看,比起最初一刻的选择,更难的是后面一长段时间的坚持:项目怎么从实验室走到市场?第一笔订单之后,第二批设备钱从哪里来&#xf…

作者头像 李华
网站建设 2026/4/18 8:38:28

SQL必会必知整理-13-联结表

13.1 联结联结是利用SQL的SELECT能执行的最重要的操作,很好地理解联结及其语法是学习SQL的一个极为重要的组成部分。13.1.1 关系表外键为某个表中的一列,它包含另一个表的主键值,定义了两个表之间的关系。这样做的好处如下:信息不…

作者头像 李华