文章目录
- 一、前言
-
- Spring Bean覆盖配置
- 二、@Autowired
-
- 注解处理器
- 装配方式
- 注解属性
- 作用范围
-
- 1. 成员变量
- 2. 构造器
- 3. 方法
- 4. 参数
- 5. 注解
- 使用技巧
-
- 同一类型多个bean
- @Primary的使用
- @Qualifier的使用
- 装配多个实例
- @Autowired装配未生效
- 三、@Resource
-
- 注解处理器
- 装配方式
- 注解属性
- 作用范围
-
- 1. 成员变量
- 2. 方法
- 3. 类
- 四、@Autowired与@Resource对比
-
- 二者对比
- @Autowired装配流程
- @Resource装配流程
一、前言
@Autowired和@Resource都是用来自动装配bean的。
- @Resource是JSR-250提供的,它是Java标准,绝大部分框架都支持。
- @Autowired功能非常强大,但只适用于Spring框架,如果换成了JFinal等其他框架,功能就会失效。
Spring Bean覆盖配置
spring:
main:
allow-bean-definition-overriding: true
allow-bean-definition-overriding属性用于配置出现相同名称bean的情况如何处理:
- 值为false时(默认值为false),如果出现相同名称的bean,直接抛异常。
- 值为true时,表示支持相同名称的bean覆盖,后定义的bean会覆盖之前定义的相同名称的bean。
下文会提到按类型装配,那么什么是同一类型呢?
- 父类及其子类,都属于父类这一类型。
- 接口及其实现类,都属于接口这一类型。
二、@Autowired
@Autowired是Spring提供的注解,用于自动装配。
注解处理器
AutowiredAnnotationBeanPostProcessor类是Autowired注解的注解处理器。
关于注解处理器可参考文章:https://blog.csdn.net/JokerLJG/article/details/123548694
装配方式
- 按类型装配(默认使用的装配方式)。
- 按名称装配(结合@Qualifier注解使用)。
注解属性
- required:默认值true。值为true时,表示必须注入,如bean不存在则会报错;值为false时,表示bean存在就注入,不存在则不注入。
作用范围
@Autowired的作用范围:成员变量、构造器、方法、参数、注解。
1. 成员变量
@Service
public class UserService {
@Autowired
private IUser user;
}
使用最多的方式。
2. 构造器
@Service
public class UserService {
private IUser user;
@Autowired
public UserService(IUser user) {
this.user = user;
}
}
构造器上使用Autowired注解,实际上还是使用了成员变量装配的方式,并非构造器装配。
3. 方法
@Service
public class UserService {
@Autowired
public void test(IUser user) {
user.test();
}
}
Spring会在项目启动的过程中,自动调用一次加了@Autowired注解的方法,我们可以在该方法做一些初始化的工作。
4. 参数
在构造器的入参上加Autowired注解
@Service
public class UserService {
private IUser user;
public UserService(@Autowired IUser user) {
this.user = user;
System.out.println("user:" + user);
}
}
在非静态方法的入参上加Autowired注解
@Service
public class UserService {
public void test(@Autowired IUser user) {
user.test();
}
}
5. 注解
略。
使用技巧
同一类型多个bean
当按类型装配时,如果该类型的bean不止一个时,会直接报错。举例说明:
接口:
public interface IUser {
void test();
}
实现类1:
@Service
public class User1 implements IUser{
@Override
public void test() {
}
}
实现类2:
@Service
public class User2 implements IUser{
@Override
public void test() {
}
}
自动装配:
@Service
public class UserService {
@Autowired
private IUser user;
}
启动时的错误信息:
Field userService in com.joker.controller.UserController required a single bean, but 2 were found:
- userServiceImpl1: defined in file [D:\work\my\springboot\target\classes\com\joker\controller\UserServiceImpl1.class]
- userServiceImpl2: defined in file [D:\work\my\springboot\target\classes\com\joker\controller\UserServiceImpl2.class]
@Primary的使用
@Primary注解可以解决上述问题(按类型装配时,如果该类型的bean不止一个时,会报错)。
当我们使用自动配置的方式装配Bean时,如果这个Bean有多个候选者,假如其中一个候选者具有@Primary注解修饰,该候选者会被选中,作为自动装配的bean。
在上面代码不变的情况下,只需在User1或User2上加@Primary注解,此时@Autowired自动装配会成功,并且自动装配的是加了@Primary注解的这个类对应的bean。
User1类加@Primary注解
@Service
@Primary
public class User1 implements IUser{
@Override
public void test() {
}
}
@Qualifier的使用
通过@Autowired和@Qualifier的结合使用可以按名称装配。
@Service
public class UserService {
@Autowired
@Qualifier("user1")
private IUser user;
}
自动装配名称为user1的bean(注意:bean的类型也必须要满足为IUser类型)。
装配多个实例
我们一般使用的都是用@Autowired自动装配单个实例,但其实它也可以用来装配多个实例。可以通过List、Set、Map来装配多个实例,如下:
@Service
public class UserService {
@Autowired
private List<IUser> userList;
@Autowired
private Set<IUser> userSet;
@Autowired
private Map<String, IUser> userMap;
}
上面的装配方式会吧IUser类型的多个实例bean都装配的List、Set、Map中。
@Autowired装配未生效
下面列举常见@Autowired装配未生效的情况:
-
@Autowired所在类未加@Controller、@Service、@Component、@Repository等注解,或者或者一些其它情况(如直接new对象的到实例)。这些情况会导致该类的bean并没有交给spring容器去管理,spring就无法完成自动装配的功能。
public class UserService { @Autowired private IUser user; public void test() { user.say(); } }
-
注解未被@ComponentScan扫描到。
三、@Resource
@Resource是JDK自带的注解,用于自动装配。
注解处理器
CommonAnnotationBeanPostProcessor类是Resource的注解处理器。
装配方式
@Resource默认按照名称自动注入。
-
既没指定name,也没指定type,自动按照名称装配(当注解写在字段上时,默认取字段名,当注解写在setter方法上时,默认取属性名进行装配。);如果没有匹配,则退而按照类型装配,找不到则抛出异常。
如果没有指定 name 属性,
-
如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
-
如果指定了type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。
-
如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
注解属性
Resource注解的主要属性:
- name:指定需注入的bean的名称
- type: 指定需注入的bean的类型
作用范围
@Resource的作用范围:类、成员变量、方法。
1. 成员变量
@Service
public class UserService {
@Resource
private IUser user;
}
2. 方法
@Service
public class UserService {
@Resource
public void test(IUser user) {
user.test();
}
}
3. 类
略。
四、@Autowired与@Resource对比
二者对比
@Autowired | @Resource |
---|---|
Spring定义的注解 | JSR-250定义的注解 |
默认按类型自动装配 | 默认按名称自动装配 |
一个参数:required(默认true),表示是否必须注入 | 七个参数:最重要的两个参数是name、type |
默认按类型自动装配 如果要按名称自动装配,需要使用@Qualifier一起配合 |
默认按名称自动装配 如果指定了name,则按名称自动装配;如果指定了type,则按类型自动装配 |
作用范围:构造器、方法、参数、成员变量、注解 | 作用范围:类、成员变量、方法 |