BiliBiliToolPro终极指南:如何高效自动化你的B站日常任务
2026/6/23 23:54:55
总结:@Configuration用来定义Java 配置类,用@Bean方法声明 Spring 管理的 Bean;Spring 会把它当作配置信息并用 CGLIB 动态代理(默认)处理,从而保证@Bean方法的单例语义与依赖注入正确。
下面分条讲清楚你必须掌握的点(配合例子和常见面试问答)。
@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。@Configuration与@Component的区别@Configuration本身带有@Component(因此可以被扫描),但它的语义比普通@Component更强:@Configuration类会被 Spring 用 CGLIB 生成子类(代理),以保证同一配置类中@Bean方法相互调用时仍然返回容器管理的单例实例。@Component+@Bean(理论上也能),则不会有 proxy 的增强语义,互相调用会直接执行方法(可能导致重复实例化)。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 = true:a()内部调用b()实际会走代理,返回容器中的B单例。proxyBeanMethods = false:a()直接调用b()方法,返回的是新创建的 B 实例,会破坏单例语义。@Configuration时,会把该类变成一个代理子类(CGLIB),当在配置类内调用b()时,调用会被拦截,代理去容器中取B(如果已存在),而不是直接在方法体内 new 一个新对象。@Configuration类声明为final(CGLIB 需要继承)。@Configuration常和以下注解一起使用:@Bean:声明一个 bean。@Import:引入其他配置类或配置组件。@Profile:按环境条件激活配置。@PropertySource:加载属性文件(但在 Spring Boot 中通常使用application.properties/yml)。@Enable*(例如@EnableTransactionManagement)用于开启某些功能。@ConfigurationProperties与@Configuration不同:前者用于绑定配置属性。@Bean方法内部可以用构造器或者 setter 来注入依赖(示例里用 new 时手动传入)。@Bean方法参数中声明需要注入的其他 bean,Spring 会自动注入(更推荐):@Bean public UserService userService(UserRepository repo) { return new UserService(repo); }此方式可避免proxyBeanMethods的问题(因为注入在容器层面已完成)。
@Configuration类标记为final— CGLIB 代理需要继承。@Configuration(proxyBeanMethods=false),切忌在同一类中互相调用@Bean方法(会创建多个实例)。@Bean互不依赖,可以用proxyBeanMethods=false提升性能(Spring Boot 的自动配置大量使用该优化)。@Configuration会被ConfigurationClassPostProcessor处理,发生在常规 bean 定义之前。@Bean不会生效(需要 component-scan、@Import 或在 ApplicationContext 注册)。@Bean方法不要写为private(Spring 需要能调用/代理)。@Configuration的作用?@Bean注册 Spring Bean;Spring 会对该类进行特殊处理(默认 proxyBeanMethods=true)。@Configuration和@Component有什么不同?@Configuration会被 Spring 作为配置并生成代理以保证@Bean方法互调仍返回容器的唯一 Bean;@Component没有这些语义。proxyBeanMethods?true(默认):保证方法间互调返回容器中的单例;false:不代理,性能更好但会失去方法调度保障。@Configuration类可以是final吗?final,因为默认是通过子类代理(CGLIB)。@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),造成重复实例。@Configuration而不是 XML / 注解扫描?@Configuration(类型安全、可重构、IDE 支持好)。XML 仅在需要兼容老系统或某些特殊场景时使用。