Spring让读取和存储Bean更加简单(下篇)——使用注解获取Bean对象

举报
未见花闻 发表于 2022/08/31 22:00:00 2022/08/31
【摘要】 本篇文章将介绍使用Spring获取已经储存在Spring容器中的对象,注入的方式有三种,分别为属性注入,构造方法注入(目前官方推荐),Setter方法注入(老版本Spring官方推荐)。

⭐️前面的话⭐️

本篇文章将介绍使用Spring获取已经储存在Spring容器中的对象,注入的方式有三种,分别为属性注入,构造方法注入(目前官方推荐),Setter方法注入(老版本Spring官方推荐)。

📒博客主页:未见花闻的博客主页
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
📌本文由未见花闻原创,CSDN首发!
📆首发时间:🌴2022年8月31日🌴
✉️坚持和努力一定能换来诗与远方!
💭推荐书籍:📚《Spring实战》
💬参考在线编程网站:🌐牛客网🌐力扣
博主的码云gitee,平常博主写的程序代码都在里面。
博主的github,平常博主写的程序代码都在里面。
🍭作者水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!

1.前言

前面我们已经介绍了如何使用注解将对象储存到Spring中,你把对象储存到Spring中了,如果你想使用这些对象,还得从Spring中取出来,最开始介绍Spring的时候,已经介绍过使用上下文和Bean工厂来获取对象,本文将介绍使用注解来实现对象的读取。

使用注解可以直接将已经储存的对象取出来,直接赋值到注解所在类的一个属性中,这一个过程也叫做对象的装配或者叫对象的注入。

2.使用注解获取Bean

2.1对象注入的概念

获取 bean 对象也叫做对象装配,就是把对象取出来放到某个类中,有时候也叫对象注入。
对象装配(对象注入)的实现方法以下 3 种:

  1. 属性注入 ,就是将对象注入到某个类的一个属性当中。
  2. 构造方法注入 ,就是通过构造方法来将对象注入到类中。
  3. Setter方法 注入 ,通过SetXXX系列方法将对象注入到类中。

常见有关对象注入的注解有两个,一个是@Autowired,另外一个是@Resource,其中@Autowired支持属性注入,构造方法注入和Setter注入,@Resource支持属性注入和Settter注入,但是不支持构造方法注入。

说到这里,我们来说一说@Autowired与@Resource的区别吧,两者的区别有:

  • 前面说的,@Autowired支持属性注入,构造方法注入和Setter注入,@Resource支持属性注入和Settter注入,但是不支持构造方法注入。
  • @Autowired是Spring提供的,@Resource是JDK提供的。
  • @Resource支持更多的参数设置,如name type等,而@Autowired只支持设置required参数。

2.2属性注入

属性注入很简单,我们只需要在需要注入对象的属性上加上@Autowired或者@Resource注解就可以了,我们以@Autowired为例。

第一种情况,待注入的同类对象只有一个,这时我们直接使用@Autowired注解就好,不必设置参数,例如我们在UserController类里面注入UserService对象。

UserService类结构:

@Service
public class UserService {
    public void sayHi() {
        System.out.println("你好! Service");
    }
}

属性注入:

@Controller
public class UserController1 {
    //属性注入
    @Autowired
    private UserService service;

    public void sayHi() {
        service.sayHi();
    }
}

然后我们就可以在启动类中,使用上下文对象来获取UserController1对象,通过执行UserController1对象的sayHi方法来间接执行UserService对象的sayHi方法,这样我们就不用new一个UserService对象了。

public class Main6 {
    public static void main(String[] args) {
        //获取UserController1的对象
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

        UserController1 controller1 = (UserController1) context.getBean("userController1");
        controller1.sayHi();
    }
}

运行结果:
1
但是如果存在多个同类对象,我们就得通过参数来告知注解我们要注入哪一个对象,不告知就会报错,比如我们注入了多个User对象,在Controller2类中需要注入User对象,此时我们运行程序就会报错:
2

UserController2类:

@Controller
public class UserController2 {
    @Autowired
    private User user;

    public void sayHi() {
        System.out.println("User" + user);
    }
}

我们试着以同样的方法来执行sayHi方法:

3
运行结果:
4

下面我们来告知注解我们需要哪一个类的方法,有三种方法:

  • 对于属性注入,将属性的变量名设置为你需要的那个BeanName就可以了,因为Spring会优先寻找与变量名相同的对象,构造方法与Setter注入也是同理,将形参名设置与BeanName相同即可。
  • 设置@Resource注解的参数nameBeanName,就是重命名。
  • @Autowired注解与@Qualifier注解配合,设置@Qualifier的value参数为BeanName即可,注意@Qualifier注解不能修饰方法,只能修饰变量。

下面我们详解如何设置参数。

@Autowired或者@Resource注解在设置参数这一方面是有差别的,我们分开来讨论,首先我们来看看如何使用@Resource注解获得目标对象,其实很简单,在@Resource注解有一个name参数,我们将我们所需要的对象名称作为参数传进去就可以了,就像下面这样:

@Controller
public class UserController3 {
    @Resource(name = "userinfo")
    private User user;
    
    public void sayHi() {
        System.out.println("User" + user);
    }
}

启动类的获取UserController3类的逻辑是一样的,我就不贴代码了,我们直接来看运行结果:
5
成功注入了对象,我们再来看看@Autowired注解怎么指定对象,因为@Autowired注解没有name参数,我们需要使用一个辅助注解@Qualifier来设置,它可以用来定义名称,该注解只有一个参数value,将这个value参数值设置为对象名称就可以了。

@Controller
public class UserController2 {
    @Autowired
    @Qualifier(value = "userinfo")
    private User user;

    public void sayHi() {
        System.out.println("User" + user);
    }
}

运行结果:

6
嘿嘿,也成功了,下面我们就继续介绍其他的注入方法。

2.3构造方法注入

用法如下,就是在构造方法加上@Autowired注解,注意@Resource注解不可以,它不支持,我们直接演示如何取多个同类对象中的一个吧,假设你需要userinfo对象,具体示例如下:

方法1:@Autowired搭配@Qualifier

@Controller
public class UserController4 {
    private User user;
    @Autowired
    public UserController4(@Qualifier(value = "userinfo") User user) {
        this.user = user;
    }

    public void sayHi() {
        System.out.println("User" + user);
    }
}

方法2:将构造方法形参名设置为userinfo

@Controller
public class UserController4 {
    private User user;
    @Autowired
    public UserController4(User userinfo) {
        this.user = userinfo;
    }

    public void sayHi() {
        System.out.println("User" + user);
    }
}

运行结果都是一样的:
7
如果一个类中只有一个构造方法,@Autowired可以省略,如果一个类中有多个构造方法,@Autowired一定不能省!省略就会导致会注入对象失败。

示例:只有一个构造方法省略@Autowired

@Controller
public class UserController4 {
    private User user;

    public UserController4(User userinfo) {
        this.user = userinfo;
    }

    public void sayHi() {
        System.out.println("User" + user);
    }
}

仍然可以成功注入对象。
8
示例2:多个构造方法,省略@Autowired

@Controller
public class UserController4 {
    private User user;

    public UserController4(User userinfo) {
        this.user = userinfo;
    }
    
    public UserController4() {
        System.out.println("Hi");
    }

    public void sayHi() {
        System.out.println("User" + user);
    }
}

我们来运行一下,注入对象失败咯,输出的结果是null,至于前面那个Hi怎么来的,因为默认调用了无参的构造方法了,无参构造方法里面输出了Hi

9
加上@Autowired注解就能正常获取了,我就不演示了。

2.4Setter注入

Setter注入与构造方法注入大同小异,就是在SetXXX系列方法进行注入,简单做个示例吧,同样我们还是注入userinfo这个对象。

@Controller
public class UserController5 {
    private User user;

    @Autowired
    public void setUser(User userinfo) {
        this.user = userinfo;
    }

    public void sayHi() {
        System.out.println("User" + this.user);
    }
}

当然,还可以使用@Resource注解,使用方式与@Autowired也是一样的,如果需要指定注入对象,和前面说的一样,要么修改变量名,要么设置参数。

2.5三种注入方式的区别

三种注入方式都可以实现对象的注入,早期的Spring版本,官方推荐使用Setter注入,原因据说是因为构造方法的参数可能较多而不推荐构造方法注入,现在的Spring版本,官方推荐构造方法注入,原因据说是因为构造方法的通用性高于Setter注入,之所以这么说,是因为其他的高级编程语言,构造方法都是类似的,但是Setter方法其他语言没有Java这么复杂。下面说区别吧:

  • 属性注入特点写法简单。但是通用性不好,它只能运行在IoC容器下,如果是非IoC 容器就会出现问题。
  • Setter 注入,早期Spring 版本推荐的写法,Setter 注入通用性没有构造方法注入通用。
  • 构造方法注入,通用性更好、它能确保在使用注入对象之前,此注入对象一定初始化过了。当构造方法注入参数过多时,此时开发者就要检查自己所写的代码是否符合单一设计原则的规范了,此注入方式也是spring后期版本中推荐的注入方式。
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。