Spring核心:@Configuration注解详解
聊聊 Spring 框架中的 @Configuration
注解。
核心概念
@Configuration
是一个核心的 Spring 注解,它表明这个类是一个【配置类】。 它的主要作用是替代传统的 XML 配置文件,允许开发者使用纯 Java 代码来定义和配置 Spring 应用上下文中的 Bean。
你可以把它理解为 <beans>
标签的 Java 等价物。
主要作用与特性
1. 定义 Bean
在配置类中,你可以使用 @Bean
注解在方法上,该方法返回的对象将被 Spring 容器注册为一个 Bean。
传统 XML 方式:
<beans><bean id="myService" class="com.example.MyServiceImpl"/>
</beans>
现代 @Configuration
方式:
@Configuration
public class AppConfig {@Beanpublic MyService myService() {return new MyServiceImpl();}
}
2. 配置 Bean 的依赖关系
你可以在一个 @Bean
方法中调用另一个 @Bean
方法,Spring 会确保这是对单例 Bean 的引用,而不是普通的方法调用。
@Configuration
public class AppConfig {@Beanpublic DataSource dataSource() {return new DriverManagerDataSource(...);}// userRepository() 依赖于 dataSource()@Beanpublic UserRepository userRepository() {return new JdbcUserRepository(dataSource()); // 这里调用的是被 Spring 拦截的方法,返回的是单例 Bean}// userService() 依赖于 userRepository()@Beanpublic UserService userService() {return new UserServiceImpl(userRepository());}
}
3. 组合配置(模块化)
你可以使用 @Import
注解来组合多个配置类,实现模块化配置。
@Configuration
public class DatabaseConfig {@Beanpublic DataSource dataSource() { ... }
}@Configuration
public class ServiceConfig {@Beanpublic UserService userService() { ... }
}// 主配置类导入其他配置
@Configuration
@Import({DatabaseConfig.class, ServiceConfig.class})
public class AppConfig {
}
4. 与组件扫描配合使用
@Configuration
经常与 @ComponentScan
一起使用,以自动发现并注册使用 @Component
, @Service
, @Repository
等注解的类。
@Configuration
@ComponentScan("com.example") // 扫描 com.example 包及其子包下的所有组件
public class AppConfig {// 也可以在这里用 @Bean 定义一些特殊的、需要复杂配置的 Bean
}
工作原理:底层魔法(CGLIB 代理)
这是 @Configuration
类最精妙的地方。Spring 在运行时会对 @Configuration
类使用 CGLIB 字节码增强。
这意味着:
-
Spring 容器会创建你的配置类的一个子类代理。
-
当调用
@Bean
方法时,代理会首先检查容器中是否已经存在该 Bean。 -
如果存在,则返回已存在的单例实例;如果不存在,才真正执行方法体来创建 Bean,并将其放入容器。
这就是为什么在上面的例子中,userRepository()
方法里调用 dataSource()
不会创建一个新的 DataSource
实例,而是返回 Spring 容器中那个唯一的单例。
对比: 如果在一个普通的 @Component
类中使用 @Bean
方法,则不会有这个代理行为,每次调用 dataSource()
都会执行一次 new
,这通常不是你想要的。
@Configuration
vs @Component
虽然 @Configuration
本身也被 @Component
元注解标记(意味着它也能被组件扫描到),但它们有明确的区别:
特性 |
|
|
---|---|---|
主要目的 | 配置和定义 Bean | 作为通用组件被扫描 |
| 通过 CGLIB 代理,确保返回单例 Bean | 作为普通 Java 方法调用,可能创建新对象 |
语义 | 明确表示这是一个配置类 | 表示一个通用的 Spring 组件 |
最佳实践和总结
-
核心配置:用于定义应用的核心配置、数据源、第三方库集成等无法使用
@ComponentScan
自动注册的 Bean。 -
替代 XML:是现代 Spring 和 Spring Boot 应用中首选的配置方式,完全取代了繁琐的 XML 配置。
-
与
@Bean
搭档:@Configuration
是舞台,@Bean
方法是舞台上的演员,二者密不可分。 -
Spring Boot 的核心:Spring Boot 的自动配置就是通过大量的
@Configuration
类来实现的。
一句话总结:
@Configuration
是 Spring 的“蓝图”类,它使用 Java 代码清晰地定义了你的应用中需要哪些 Bean 以及它们之间如何协作,是 Spring IoC 容器的编程式配置核心。