Spring 核心注解全解析:从配置到实战
Spring 框架的注解体系是简化开发、实现 “约定优于配置” 的核心。从早期的 XML 配置到现在的全注解开发,注解极大地提升了开发效率。本文将系统整理 Spring 常用注解,按功能分类详解其作用、用法及适用场景,帮助开发者快速掌握注解的使用技巧。
配置类与 Bean 定义注解
这类注解用于替代 XML 配置文件,实现 Bean 的定义与配置类的声明,是注解开发的基础。
1. @Configuration
作用:标记类为 Spring 配置类,相当于 XML 配置中的
<beans>
标签。特点:配置类中可通过
@Bean
定义 Bean,容器启动时会扫描并加载这些配置。示例:
1
2
3
4
5
6
7
8// 声明为配置类
public class AppConfig {
// 定义 Bean(方法名默认作为 Bean 的 id)
public UserService userService() {
return new UserService();
}
}
2. @Bean
作用:在配置类中定义 Bean,相当于 XML 中的
<bean>
标签。核心属性:
name/value
:指定 Bean 的 id(默认是方法名);initMethod
:Bean 初始化方法(相当于 XML 的init-method
);destroyMethod
:Bean 销毁方法(相当于 XML 的destroy-method
)。
示例:
1
2
3
4
public UserDao userDao() {
return new UserDao();
}
3. @Scope
作用:指定 Bean 的作用域(生命周期范围)。
常用值:
singleton
(默认):单例,容器中只有一个实例,随容器启动创建;prototype
:原型,每次获取时创建新实例;request
:Web 环境中,每个请求对应一个实例;session
:Web 环境中,每个会话对应一个实例。
示例:
1
2
3
4
5
// 原型模式,每次获取创建新对象
public User user() {
return new User();
}
4. @Lazy
作用:延迟加载单例 Bean(默认单例 Bean 随容器启动创建)。
适用场景:Bean 初始化耗时较长(如加载大量数据),希望首次使用时再创建。
示例:
1
2
3
4
5
// 单例 Bean 首次使用时才初始化
public CacheService cacheService() {
return new CacheService();
}
5. @Conditional
作用:根据条件动态注册 Bean(Spring 4+ 新增)。
用法:配合
Condition
接口,实现条件判断逻辑。示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// 自定义条件:仅当系统为 Windows 时注册 Bean
public class WindowsCondition implements Condition {
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getEnvironment().getProperty("os.name").contains("Windows");
}
}
public class SystemConfig {
// 满足 Windows 条件才注册
public SystemService windowsService() {
return new WindowsService();
}
}
6. @Primary
作用:当存在多个同类型 Bean 时,指定默认被注入的 Bean。
解决问题:避免
@Autowired
因类型匹配多个 Bean 而抛出异常。示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 默认注入该数据源
public DataSource primaryDataSource() {
return new DruidDataSource();
}
public DataSource secondaryDataSource() {
return new HikariDataSource();
}
// 注入时会自动选择 primaryDataSource
private DataSource dataSource;
7. FactoryBean(接口,非注解)
作用:通过工厂模式创建复杂 Bean(间接定义 Bean 的一种方式)。
特点:
getObject()
返回实际 Bean 实例,getObjectType()
指定类型。示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28// 定义工厂 Bean
public class UserFactoryBean implements FactoryBean<User> {
public User getObject() throws Exception {
User user = new User();
user.setName("工厂创建的用户");
return user;
}
public Class<?> getObjectType() {
return User.class;
}
}
// 配置类中注册工厂 Bean
public class FactoryConfig {
public UserFactoryBean userFactoryBean() {
return new UserFactoryBean();
}
}
// 获取时,默认返回 User 实例(非工厂本身)
User user = context.getBean(User.class);
// 获取工厂本身需加 & 前缀
UserFactoryBean factory = context.getBean("&userFactoryBean", UserFactoryBean.class);
组件扫描与导入注解
这类注解用于自动扫描组件或导入外部配置,简化 Bean 的注册流程。
1. @ComponentScan
作用:自动扫描指定包下的组件(标注
@Component
、@Controller
、@Service
、@Repository
的类),相当于 XML 的<context:component-scan>
。核心属性:
basePackages
:指定扫描的包路径;includeFilters
:指定需要包含的组件(需配合useDefaultFilters = false
);excludeFilters
:指定需要排除的组件。
示例:
1
2
3
4
5
6
7
8
9
10
11
// 扫描 com.example 包,排除 @Controller 组件
public class ScanConfig {
}
2. @Import
作用:导入外部组件到容器中,相当于 XML 的
<import>
。三种用法:
- 直接导入类:Bean 的 id 为全类名;
- 通过 ImportSelector 接口:动态返回需要导入的类名数组;
- 通过 ImportBeanDefinitionRegistrar 接口:手动注册 Bean 到容器。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// 1. 直接导入类
// 导入 User 和 Role 作为 Bean
public class ImportConfig {
}
// 2. 通过 ImportSelector
public class MyImportSelector implements ImportSelector {
public String[] selectImports(AnnotationMetadata metadata) {
return new String[]{"com.example.Permission"}; // 返回需要导入的类
}
}
// 导入 Selector 指定的类
public class ImportSelectorConfig {
}
3. @ImportResource
作用:导入 XML 配置文件,实现注解与 XML 配置的混合使用。
适用场景:遗留项目中存在 XML 配置,需在注解配置中复用。
示例:
1
2
3
4
// 导入 XML 配置
public class MixedConfig {
}
依赖注入与装配注解
这类注解用于实现 Bean 之间的依赖注入,替代 XML 中的 <property>
或 <constructor-arg>
。
1. @Autowired
作用:自动按类型注入依赖(默认要求依赖必须存在)。
特点:
- 可标注在字段、构造方法、setter 方法上;
- 结合
@Qualifier
可按名称注入; required = false
允许依赖为 null。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class UserService {
// 字段注入
// 指定注入 id 为 userDao 的 Bean
private UserDao userDao;
// 构造方法注入(推荐,便于测试)
public UserService(RoleService roleService) {
this.roleService = roleService;
}
// setter 方法注入
// 允许为 null
public void setLogService(LogService logService) {
this.logService = logService;
}
}
2. @Resource(JSR-250 规范)
作用:类似
@Autowired
,但默认按名称注入(兼容 Spring)。与 @Autowired 区别:
@Autowired
是 Spring 注解,@Resource
是 Java 规范注解;@Resource
可通过name
属性指定 Bean 名称,@Autowired
需配合@Qualifier
。
示例:
1
2
3
4
5
public class OrderService {
// 按名称注入 orderDao
private OrderDao orderDao;
}
3. @Qualifier
- 作用:配合
@Autowired
按名称注入 Bean,解决同类型多个 Bean 的冲突。 - 示例:见
@Autowired
的用法。
4. @Required(较少使用)
- 作用:标注在 setter 方法上,要求该属性必须在配置中被赋值(否则启动报错)。
- 注意:Spring 5+ 已废弃,推荐使用构造方法注入替代。
5. @DependsOn
作用:强制指定 Bean 的加载顺序,确保依赖的 Bean 先初始化。
适用场景:Bean A 依赖 Bean B 的初始化逻辑(如静态资源加载)。
示例:
1
2
3
4
5
// 确保 cacheService 先加载
public class UserService {
// 依赖 cacheService 的初始化结果
}
属性赋值与配置注解
这类注解用于为 Bean 的属性赋值,尤其是读取外部配置文件中的值。
1. @Value
作用:为属性赋值,支持三种类型的值:
- 字面量(如字符串、数字);
- SpEL 表达式(
#{}
); - 外部配置文件中的值(
${}
)。
示例:
1
2
3
4
5
6
7
8
9
10
11
public class AppConfig {
// 字面量
private String appName;
// SpEL 表达式(随机数)
private double randomValue;
// 外部配置文件中的值
private int port;
}
2. @PropertySource
作用:加载外部 properties 配置文件,配合
@Value
读取配置。示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 加载类路径下的配置文件
public class PropertyConfig {
public TestBean testBean() {
return new TestBean();
}
}
// app.properties 内容:test.name=张三
public class TestBean {
// 读取配置文件中的值
private String name;
}
3. @PropertySources
作用:组合多个
@PropertySource
,加载多个配置文件。示例:
1
2
3
4
5
6
7
public class MultiPropertyConfig {
}
Bean 生命周期注解
这类注解用于定义 Bean 初始化和销毁时的回调逻辑。
1. @PostConstruct(JSR-250 规范)
作用:标注在方法上,该方法在 Bean 构造完成后、初始化前执行(相当于
init-method
)。示例:
1
2
3
4
5
6
7
public class UserService {
// 初始化后执行(如加载缓存)
public void init() {
System.out.println("UserService 初始化完成");
}
}
2. @PreDestroy(JSR-250 规范)
作用:标注在方法上,该方法在 Bean 销毁前执行(相当于
destroy-method
)。示例:
1
2
3
4
5
6
7
public class OrderService {
// 销毁前执行(如释放资源)
public void destroy() {
System.out.println("OrderService 即将销毁");
}
}
环境与 Profile 注解
这类注解用于实现多环境配置(如开发、测试、生产环境的差异化配置)。
1. @Profile
作用:指定 Bean 在特定环境下才会被注册。
使用方式:
- 标注在类或方法上;
- 通过
spring.profiles.active
指定当前环境(如-Dspring.profiles.active=dev
)。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class DataSourceConfig {
// 开发环境数据源
public DataSource devDataSource() {
return new HikariDataSource();
}
// 生产环境数据源
public DataSource prodDataSource() {
return new DruidDataSource();
}
}
功能开启注解(@Enable*)
Spring 通过 @Enable*
注解开启特定功能,底层通过 @Import
导入相关配置,简化功能启用流程。
注解 | 作用 | 对应 XML 配置 |
---|---|---|
@EnableAspectJAutoProxy |
开启 AOP 自动代理(支持 @Aspect ) |
<aop:aspectj-autoproxy/> |
@EnableTransactionManagement |
开启注解式事务(支持 @Transactional ) |
<tx:annotation-driven/> |
@EnableAsync |
开启异步方法支持(支持 @Async ) |
- |
@EnableScheduling |
开启定时任务支持(支持 @Scheduled ) |
- |
@EnableWebMvc |
开启 Spring MVC 配置支持 | <mvc:annotation-driven/> |
@EnableCaching |
开启缓存支持(支持 @Cacheable 等) |
<cache:annotation-driven/> |
示例:开启事务管理
1
2
3
4
5
6
7
8
// 替代 XML 的 <tx:annotation-driven>
public class TxConfig {
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}
测试相关注解
这类注解用于 Spring 环境下的单元测试,简化测试环境搭建。
1. @RunWith(SpringJUnit4ClassRunner.class)
作用:指定 JUnit 测试的运行器为 Spring 专用运行器,用于加载 Spring 容器。
示例:
1
2
3
4
5
6
7
8
9
10
11// 整合 Spring 和 JUnit
public class UserServiceTest {
private UserService userService;
public void test() {
userService.query();
}
}
2. @ContextConfiguration
作用:指定测试时加载的 Spring 配置(配置类或 XML 文件)。
示例:
1
2
3
4// 加载配置类
// 或加载 XML 文件
总结与最佳实践
- 配置类与 Bean 定义:优先使用
@Configuration
+@Bean
替代 XML,配合@Scope
、@Lazy
控制 Bean 生命周期。 - 依赖注入:推荐构造方法注入(便于测试),结合
@Autowired
+@Qualifier
解决依赖冲突;@Resource
可作为兼容 Java 规范的替代方案。 - 属性赋值:
@Value
+@PropertySource
是读取外部配置的标准方式,Spring Boot 中可配合@ConfigurationProperties
增强。 - 多环境配置:
@Profile
是实现环境隔离的最佳选择,避免硬编码环境相关配置。 - 功能开启:
@Enable*
注解简化功能启用,无需记忆复杂的 XML 标签
v1.3.10