注入Bean的注解有哪些?有什么区别?
Spring 注入 Bean 的注解概述
- 定义:
- 在 Spring 框架中,注入 Bean 的注解用于将对象(Bean)注册到 Spring IoC 容器,或将容器中的 Bean 注入到其他 Bean 的属性、方法或构造器中。这些注解简化了依赖注入(Dependency Injection, DI)和 Bean 定义的配置。
- 分类:
- 定义 Bean 的注解:将类标记为 Bean,注册到容器。
- 依赖注入的注解:将容器中的 Bean 注入到目标对象。
- 核心包:
- 主要来自
org.springframework
(Spring 核心)和javax.annotation
(JSR-250/330)。
核心点
- 注入 Bean 的注解分为定义 Bean(如
@Component
)和依赖注入(如@Autowired
),各有不同作用和使用场景。
1. 注入 Bean 的主要注解
以下是 Spring 中常用的注入 Bean 相关注解,分为 定义 Bean 和 依赖注入 两类:
(1) 定义 Bean 的注解
这些注解用于将类标记为 Spring 管理的 Bean,注册到 IoC 容器。
注解 | 描述 | 使用场景 | 示例 |
---|---|---|---|
@Component |
通用的 Bean 定义注解,标记类为 Spring 管理的组件。 | 通用组件(如服务、工具类)。 | @Component public class MyService {} |
@Service |
语义化的 @Component ,标记服务层 Bean,表业务逻辑。 |
业务服务类。 | @Service public class UserService {} |
@Repository |
语义化的 @Component ,标记数据访问层 Bean,表 DAO,集成异常转换。 |
数据访问层(如数据库操作)。 | @Repository public class UserDao {} |
@Controller |
语义化的 @Component ,标记 MVC 控制层 Bean,处理 Web 请求。 |
Web 控制器。 | @Controller public class UserController {} |
@RestController |
结合 @Controller 和 @ResponseBody ,标记 RESTful 控制器,返回 JSON/XML。 |
REST API 控制器。 | @RestController public class ApiController {} |
@Configuration |
标记配置类,包含 @Bean 方法定义 Bean,替代 XML 配置。 |
配置类(如定义数据源)。 | @Configuration public class AppConfig {} |
@Bean |
在 @Configuration 类中定义方法返回的 Bean,显式注册到容器。 |
自定义 Bean(如第三方库)。 | @Bean public DataSource dataSource() {} |
- 区别:
@Component
是通用注解,其他如@Service
、@Repository
、@Controller
是其特化版本,功能相同但语义更明确。@Repository
额外提供持久化异常转换(DataAccessException
)。@RestController
比@Controller
更适合 REST API,自动序列化响应。@Configuration
和@Bean
用于程序化定义 Bean,适合复杂配置或第三方类。- 扫描机制:
- 需在
@ComponentScan
指定的包路径下,Spring 自动扫描这些注解。
(2) 依赖注入的注解
这些注解用于将容器中的 Bean 注入到目标对象的字段、方法或构造器。
注解 | 描述 | 使用场景 | 示例 |
---|---|---|---|
@Autowired |
Spring 专有注解,自动按类型注入 Bean,支持字段、方法、构造器。 | 通用依赖注入。 | @Autowired private UserService userService; |
@Resource |
JSR-250 标准注解,按名称(默认字段名)或类型注入,支持字段和方法。 | 跨框架兼容注入。 | @Resource(name="userService") private UserService userService; |
@Inject |
JSR-330 标准注解,类似 @Autowired ,按类型注入,支持字段、方法、构造器。 |
跨框架(如 CDI)兼容注入。 | @Inject private UserService userService; |
@Qualifier |
与 @Autowired 或 @Inject 配合,指定 Bean 名称或限定注入。 |
解决多实现类注入歧义。 | @Autowired @Qualifier("userServiceImpl") private UserService userService; |
@Value |
注入配置文件中的属性值或表达式,非 Bean 注入。 | 配置属性注入(如 application.properties )。 |
@Value("${app.name}") private String appName; |
- 区别:
@Autowired
:- Spring 专有,按类型注入,若有多个匹配 Bean,需
@Qualifier
或@Primary
限定。 - 默认
required=true
,未找到 Bean 抛异常。
- Spring 专有,按类型注入,若有多个匹配 Bean,需
@Resource
:- JSR-250 标准,按名称优先(字段名或
name
属性),未找到再按类型。 - 跨框架兼容性更好(如 EJB)。
- JSR-250 标准,按名称优先(字段名或
@Inject
:- JSR-330 标准,行为类似
@Autowired
,但无required
属性,需额外依赖(如javax.inject
)。 - 适合 CDI 或其他 DI 框架。
- JSR-330 标准,行为类似
@Qualifier
:- 辅助注解,解决类型注入的歧义。
@Value
:- 针对非 Bean 的简单属性注入(如字符串、数字)。
2. 注解使用示例
定义 Bean
@Component
public class MyComponent {
// 通用组件
}
@Service
public class UserService {
// 业务服务
}
@Repository
public class UserRepository {
// 数据访问
}
@Controller
public class UserController {
// MVC 控制器
}
@Configuration
public class AppConfig {
@Bean
public DataSource dataSource() {
return new DriverManagerDataSource();
}
}
依赖注入
@Service
public class UserService {
@Autowired // 按类型注入
private UserRepository userRepository;
@Resource(name = "myComponent") // 按名称注入
private MyComponent myComponent;
@Inject // JSR-330 注入
private DataSource dataSource;
@Value("${app.name}") // 属性注入
private String appName;
@Autowired
@Qualifier("specificImpl") // 限定注入
private SomeInterface someInterface;
// 构造器注入
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
3. 注解的区别与选择
- 定义 Bean 注解:
@Component
vs 特化注解:@Service
、@Repository
、@Controller
是语义化的@Component
,功能相同但层次清晰。@Repository
提供异常转换,适合 DAO。@RestController
简化 REST 开发。
@Configuration
和@Bean
:- 用于程序化配置,适合第三方库或复杂 Bean 定义。
@Bean
方法运行时创建 Bean,灵活性高。
- 依赖注入注解:
@Autowired
vs@Resource
vs@Inject
:@Autowired
是 Spring 首选,功能丰富(支持required
、@Qualifier
)。@Resource
按名称优先,跨框架兼容,适合简单场景。@Inject
是标准规范,跨容器(如 Spring、CDI)迁移性好。
@Qualifier
:- 解决类型冲突,如接口多个实现。
@Value
:- 专门注入配置属性,非 Bean 注入。
- 选择建议:
- Spring 项目优先
@Autowired
和@Component
系列,功能强大且生态集成好。 - 跨框架或标准规范场景用
@Resource
或@Inject
。 - 配置注入用
@Value
,复杂 Bean 定义用@Configuration
和@Bean
。
4. 注意事项
- 扫描范围:
- 定义 Bean 的注解需在
@ComponentScan
包路径下,否则不生效。 - 注入失败:
@Autowired
默认required=true
,未找到 Bean 抛NoSuchBeanDefinitionException
。- 解决:设置
required=false
或用@Qualifier
限定。 - 多实现歧义:
- 接口有多个实现时,需
@Qualifier
、@Primary
或@Resource(name)
指定。 - 性能:
- 字段注入(
@Autowired
直接在字段)可能降低可测试性,推荐构造器注入。 - 依赖:
@Inject
需javax.inject
依赖,@Resource
需javax.annotation
。
5. 面试角度
- 问“注入注解”:
- 提
@Component
系列(@Service
、@Repository
等)、@Bean
、@Autowired
、@Resource
、@Inject
。 - 问“区别”:
- 提定义 Bean(语义、功能)与注入(按类型/名称、标准)的对比。
- 问“场景”:
- 提服务层用
@Service
,DAO 用@Repository
,REST 用@RestController
,配置用@Value
。 - 问“问题”:
- 提注入失败、歧义、扫描范围。
6. 总结
Spring 注入 Bean 的注解分为定义 Bean(@Component
、@Service
、@Repository
、@Controller
、@RestController
、@Configuration
、@Bean
)和依赖注入(@Autowired
、@Resource
、@Inject
、@Qualifier
、@Value
)。定义注解注册 Bean,注入注解实现依赖注入。区别在于语义、注入方式(类型/名称)、标准兼容性和使用场景。Spring 优先 @Autowired
和 @Component
系列,跨框架用 @Resource
或 @Inject
。面试可提分类、代码示例或选择依据,清晰展示理解。