@Autowired
基本使用
直接放在属性、或方法上即可
一些细节
1、@Autowired 是先通过 byType,再 byName
整体思路是:
1、首先通过(byType)类型以及子类查找,若在单例池中找到符合条件的一个 Bean,就将其注入。这里不管 Bean 的 id 叫什么都行,叫 abcdef 也无所谓,因为不是靠这个判断。
byType 的失效条件是:Spring 单例池中存在多个符合 byType 条件的 Bean
2、如果找到多个符合条件的 Bean,则通过 byName 来根据 Bean 的 id 进行匹配
Controller
@RestController
public class HelloController {
@Autowired
private UserService userService;
}
UserService 导入容器
@Configuration
@ComponentScan(basePackages = "com.gg")
public class ConfigurationA {
// 方法名作为 Bean id
@Bean
public UserService userService() {
UserService userService = new UserService();
return userService;
}
}
到这一步没什么问题。
但如果是下面这种情况那就会出问题了:假如配置类中有两个 UserService 的 Bean 对象
现在 Spring 单例池中有多个 UserService 类型的 Bean
HelloController 需要的类型是 UserService,根据 byName 来找,则需要 id 叫 "userService" 的 Bean
但现在配置类中并没有导入符合 HelloController 需求的组件,看看如下代码:
@Configuration
@ComponentScan(basePackages = "com.gg")
public class ConfigurationA {
// 方法名作为 Bean id
@Bean
public UserService userService1() {
UserService userService = new UserService();
return userService;
}
@Bean
public UserService userService2() {
UserService userService = new UserService();
return userService;
}
}
到这里,会发现运行起来报一个错误,错误信息如下:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'helloController': Unsatisfied dependency expressed through field 'user';
nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type 'com.gg.springboot.service.UserService' available:
expected single matching bean but found 2: userService1,userService2
翻译一下最后一句话,意思是 HelloController 只允许有一个 UserService 匹配,但现在找到了两个。
故不知道用哪个合适,Spring 不能帮我们擅自做决定,所以报错!
2、byType 与 byName中间的步骤?
byType 与 byName ,他俩中间有一系列判断
执行顺序
1、首先根据 byType
2、根据 Type 从 Spring 容器里找到符合条件的多个 Bean
3、判断 autowiredCandidate(Bean 上),这个属性默认是 true,若赋值 false,则不添加到 Spring 单例池
@Bean(autowireCandidate = true)
public User user1() {
return new User("小明");
}
4、判断是否有 @Qualifier,若有,指定根据 byName ,若找不到,直接报错
@Bean
@Qualifier("user")
public User user1() {
return new User("小明");
}
5、判断是否标有 @Primary 的 Bean
6、判断是否标有 @Priority、@Order 等带有优先级的 Bean
@Primary
@Bean
public User user1() {
return new User("小明");
}
7、最终选取到合适的 Bean
优先级排序
@Primary>@Priority>@Order三个注解都是:数值越小,优先级越高(因为排在了集合的前面)
3、注解添加在方法上时
3.1@Autowired 标注在方法上时,参数名作为 Bean id,且方法名随意
private User user;
@Autowired //方法名不是set开头,照样可以获取
public void diUser(User user) {
this.user = user;
}
3.2而且同时可以注入多个参数
@Autowired
public void diUser(User user,User user2,User user3) { // 参数名作为 Bean id
this.user = user;
}
@Resource
基本使用
直接放在属性、或方法上即可
一些细节
1、@Resource是先 byName,后 byType
2、注解添加在方法上时参数只能有一个
2.1、方法名随便写
2.2、方法参数只能有一个,参数多了会报错
2.3、参数名作为 Bean id
@Resource
public void mySetUser(User user,User2) {
this.user = user;
}
重点报错信息如下
Caused by: java.lang.IllegalStateException:
@Resource annotation requires a single-arg method: public void com.gg.controller.HelloController.mySetUser(com.gg.entity.User,com.gg.entity.User)
翻译一下就是 @Resource注解需要单个参数的方法
@Autowired 与 @Resource 的区别
1、@Autowired 是 Spring 家的,@Resource 是官方提供的
2、@Autowired 在方法上时可以同时注入多个参数,@Resource在方法上时只能注入单个参数
3、@Autowired 先 byType 后 byName,@Resource先 byName 后 byType(两者的 byType 失效条件都是容器中存在多个符合条件的 Bean)