@Autowired与@Resource区别

2年前 (2022) 程序员胖胖胖虎阿
180 0 0

文章目录

  • 一、前言
    • 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装配未生效的情况:

  1. @Autowired所在类未加@Controller、@Service、@Component、@Repository等注解,或者或者一些其它情况(如直接new对象的到实例)。这些情况会导致该类的bean并没有交给spring容器去管理,spring就无法完成自动装配的功能。

    public class UserService {
    
        @Autowired
        private IUser user;
    
        public void test() {
            user.say();
        }
    }
    
  2. 注解未被@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,则按类型自动装配
作用范围:构造器、方法、参数、成员变量、注解 作用范围:类、成员变量、方法

@Autowired装配流程

@Autowired与@Resource区别

@Resource装配流程

@Autowired与@Resource区别

版权声明:程序员胖胖胖虎阿 发表于 2022年10月5日 下午1:16。
转载请注明:@Autowired与@Resource区别 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...