Spring更简单保存和获取bean对象的方法(注解)

Spring更简单保存和获取bean对象的方法

  • 前置准备
  • 将bean对象更为简单地保存到Spring容器中(使用注解)
    • 【使用类注解】 (是写在类前的)
      • 为什么要这么多类注解?
      • 类注解之间的关系
      • 使用类注解 Bean 命名规则
    • 使用方法注解(@Bean)不常用
      • 使用@bean方法注解将对象保存到Spring容器中,该bean对象的命名规则
  • 获取Spring容器的bean对象
    • 属性注入
      • 属性注入的有缺点
    • setter注入
      • Setter注入的优缺点
    • 构造方法注入
      • 构造方法注入的注意事项
      • 构造方法注入的有缺点
  • @Resource:另⼀种注⼊关键字
    • @Resource注解实现属性注入
    • @Resource注解实现setter注入
    • @Resource注解无法实现构造方法注入
    • @Resource注解和 @Autowired注解的比较
  • 同⼀类型多个 @Bean 报错问题
    • 解决方案
      • 【方法一】我们将变量名设计的跟我们要找的bean对象的id名相同就行。(这个方法不提倡使用,不太好)
      • 【方法二】使用@Resource注解的name参数或者type参数
      • 使用 @Autowired注解和 @Qualifier注解

我们介绍了通过配置spring.xml配置文件的方式来保存和获取bean对象,但是,通过配置文件的方式来保存和获取bean对象并不方便和简洁。所以,我在介绍一个更加简单和方便的方法—>通过注解的方式来保存和获取bean对象

前置准备

我们还是需要创建一个spring-config.xml配置文件,并且还需要添加一个标签来配置Spring的注解扫描路径

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:content="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <content:component-scan base-package="扫描的根目录"></content:component-scan>
    <!-- 扫描注解   -->
</beans>

将bean对象更为简单地保存到Spring容器中(使用注解)

【使用类注解】 (是写在类前的)

<1>@Controller【控制器】验证前端传递的参数【安全检查】

<2>@Service【服务】服务调用的编排和汇总

<3>@Repository【仓库】直接操作数据库

<4>@Component【组件】通用化的工具类

<5>@Configuration【配置】项目的所有配置

使用方式也很简单,只要将注解写在要给Spring管理的类前就行了(注意:要配置好扫描路径,要在扫描路劲里)

示例截图:
Spring更简单保存和获取bean对象的方法(注解)_第1张图片

为什么要这么多类注解?

就是让程序员看到类注解之后,就能直接了解当前类

的⽤途,⽐如:

@Controller:表示的是业务逻辑层;

@Service:服务层;

@Repository:持久层;

@Configuration:配置层

程序的⼯程分层,调⽤流程如下:
Spring更简单保存和获取bean对象的方法(注解)_第2张图片

类注解之间的关系

查看 @Controller / @Service / @Repository / @Configuration 等注解的源码发现,他们都有使用用@Component,

他们都是基于@Component实现的。

使用类注解 Bean 命名规则

我们在使用五个类注解让对象交给Spring管理的时候,我们可以自己给对象命名,或者使用bean的默认名字

【方式一】自己给对象命名,以@Controller为例

@Controller(“我们自己取的名字”)

【方式二】使用默认名字

规则:

一般情况:类名的第一个字母为大写,第二个字母为小写,bean的id(名字)是该类的类名,但是类名的第一个字母要改为小写

特殊情况:类名的第一个字母和第二个字母都为大小,bean的id是该类的类名.

如果类名是一个字母,不管大小写,bean的id都是类名,并且第一个字母小写

使用方法注解(@Bean)不常用

【使用方法注解】 (是写在方法前的)

@Bean

@Bean 的作用:将方法返回的对象保存到Spring的容器中

注意:

  1. @Bean不能单独使用,要搭配5大类注解使用
  2. @bean方法注解只能用在无参的方法(Spring初始化存储时,无法提供相应的参数)

使用@bean方法注解将对象保存到Spring容器中,该bean对象的命名规则

【使用默认的命名规则】

以方法名为该bean对象的id名
Spring更简单保存和获取bean对象的方法(注解)_第3张图片
【程序员可以直接设置bean对象的id名】

注意:如果程序员自己设置bean对象的id名,则bean对象默认的id名也就不能使用

<1>

@bean(name="id名字")

Spring更简单保存和获取bean对象的方法(注解)_第4张图片
<2>

@Bean(value = "id名字")

Spring更简单保存和获取bean对象的方法(注解)_第5张图片
<3>

@Bean("id名字")

Spring更简单保存和获取bean对象的方法(注解)_第6张图片
<4>一个bean对象可以设置多个id名称

@Bean(name = {"id名字","id名字"....})

Spring更简单保存和获取bean对象的方法(注解)_第7张图片

@Bean(value = {"id名字","id名字"....})

Spring更简单保存和获取bean对象的方法(注解)_第8张图片

获取Spring容器的bean对象

获取 bean 对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注⼊,有时候也叫依赖注入

对象注入的方式有三种:

  1. 属性注入(Field Injection)
  2. Setter注入(Setter Injection)
  3. 构造方法注入(Constructor Injection)

属性注入

属性注⼊是使⽤ @Autowired 实现的,在要注入的属性对象前加上@Autowired就行。

注入的前提是:要注入的对象要保存在Spring容器中

@Component
public class StudentController {
    @Autowired
    private Student student;
    public void doStudentController() {
        System.out.println("do StudentController");
        student.doStudent();
    }
}

属性注入的有缺点

优点:属性注入最大的优点就是实现简单、使用简单,只需要给变量上添加一个注解(@Autowired)

缺点:

  1. 功能性问题:不能注入一个不可变的对象(final修饰的对象)
  2. 通用性问题:只能适应于 IoC 容器
  3. 设计原则问题:更容易违背单一设计原则

setter注入

在要依赖注入的类中写一个set方法,在set方法前加上@Autowired注解就行
Spring更简单保存和获取bean对象的方法(注解)_第9张图片

Setter注入的优缺点

优点:符合单一设计的有原则(一个setter注入对应一个对象)

缺点

  1. 不能注入一个不可变的对象(final修饰的对象)

  2. 注入对象可被修改(set方法可以被多次调用,所有就有被改的风险)

构造方法注入

写一个构造方法,要依赖哪个对象,就设置哪个类型的形参,然后在构造方法前加一个@Autowired注解就行了。

(前提:注入的对象是保存在Spring容器中)

@Controller
public class UserController01 {
    //注入UserController02对象,使用属性注入
    private UserController02 userController02;
    @Autowired
    public UserController01(UserController02 userController02) {
        this.userController02 = userController02;
    }
    public void doUserController01() {
        System.out.println("user Controller01.");
        System.out.println();
        userController02.doUserController02();
    }
}

构造方法注入的注意事项

<1>使用构造方法注入时,如果构造方法只有一个,则@Autowired注解可以不写,如果有多个构造方法,则@Autowired不能不写。

只有一个构造方法,@Autowired可以不写的情况:

@Controller
public class UserController01 {
    //注入UserController02对象,使用属性注入
    private UserController02 userController02;
//    @Autowired
    public UserController01(UserController02 userController02) {
        this.userController02 = userController02;
    }
    public void doUserController01() {
        System.out.println("user Controller01.");
        System.out.println();
        userController02.doUserController02();
    }
}

<2>有多个构造方法的情况:

  1. 我们从Spring获取的bean对象会使用添加了 @Autowired注解的构造方法进行创建和对象注入
  2. @Autowired注解只能使用在一个构造方法前面,如果使用在多个构造方法前面,则我们在获取Spring上下文对象的时候会有错误。(非常好理解:我们在创建对象的时候只能使用一个构造方法,类比过来是一样的)
  3. 使用构造方法注入的时候,构造方法里面的参数必须要保存在Spring容器中才行,要不然在获取Spring上下文对象的时候会报错
  4. 我们使用构造方法注入的时候,如果重载了多个构造方法,但是,不选择一个构造方法添加@Autowired注解,这样在获取Spring上下文对象的时候,依然会保存,Spring在获取该对象的时候,它不知道要使用哪个构造方法
  5. 我们在使用构造方法注入的时候,重载了多个构造方法,其中有一个构造方法什么值都不传,可以以不添加@Autowired注解,但是,我们在获取Spring上下文的时候,创建bean对象时就会默认调用没有参数的构造方法

构造方法注入的有缺点

优点:

  1. 可以注入final修饰的对象
  2. 注入的对象不会被修改
  3. 依赖的对象在使用前会被完全初始化
  4. 通用性更好

@Resource:另⼀种注⼊关键字

之前我们在实现 属性注入、setter注入和构造方法注入 是 使用 @Autowired注解 来实现的。@Autowired注解是Spring框架提供的注解。而@Resource则是java自己提供的注解。

@Resource注解实现属性注入

用法和@Autowired注解是一样的

@Controller
public class UserController01 {
    @Resource
    private UserController02 userController02;

    public void doUserController01() {
        System.out.println("user Controller01.");
        System.out.println();
        userController02.doUserController02();
    }
}

@Resource注解实现setter注入

用法和@Autowired注解是一样的

@Controller
public class UserController01 {

    private UserController02 userController02;
    @Resource
    public void setUserController02(UserController02 userController02) {
        this.userController02 = userController02;
    }

    public void doUserController01() {
        System.out.println("user Controller01.");
        System.out.println();
        userController02.doUserController02();
    }
}

@Resource注解无法实现构造方法注入

Spring更简单保存和获取bean对象的方法(注解)_第10张图片
我们能很清楚的看到,@Resource注解放到构造方法前就直接报错了

@Resource注解和 @Autowired注解的比较

相同点:

@Resource注解和 @Autowired注解都能实现对象注入

不同点:

  1. 出身不同:@Resource注解是由java自己提供的,而@Autowired注解是由Spring提供的

  2. 依赖注入的用法不同: @Autowired注解可以实现属性注入、setter注入和构造方法注入

    而@Resource注解只能实现属性注入和setter注入 ,@Resource注解不能实现构造方法注入

  3. 支持的参数不同

    @Resource注解里面可以设置很多种参数,而@Autowired注解只能设置一种参数
    Spring更简单保存和获取bean对象的方法(注解)_第11张图片
    依赖查找的顺序不同

@Autowired注解先查找Spring容器中是否用要依赖类的类型,找到后,如果有多个则在通过比较bean对象的id名称

而@Resource注解先是通过比较bean对象的id名称来进行配对,找到后,如果有多个,则通过类型进行配对

这里需要特别注意一下:这里我们要清楚是哪几个id名称进行比较,一个是我们在Spring容器中找到多个符合的bean对象的id名称 和 我们在创建要注入依赖对象的变量名进行比较

同⼀类型多个 @Bean 报错问题

我们在使用@Bean方法注解或者使用xml配置的方法来将对象保存到Spring容器中的时候,很有可以会出现有比较多类型相同,但是bean对象的id名称不同 的情况。我们在使用注解进行对象注入的时候会比较容易出现一下的异常
Spring更简单保存和获取bean对象的方法(注解)_第12张图片
意思就是:找到了几个符合类型的bean对象,但是按bean id名匹配没有成功,所有就报错

解决方案

【方法一】我们将变量名设计的跟我们要找的bean对象的id名相同就行。(这个方法不提倡使用,不太好)

原因:不管@Resource注解和 @Autowired注解在注入对象的时候,都会有按照bean对象的id名来匹配,而我们写的变量名就是用来作比较的bean对象的id名。

【方法二】使用@Resource注解的name参数或者type参数

@Resource注解的name参数就是用来设置要匹配哪个bean对象的id名称

@Resource注解的type参数可以用来设置要注入对象的类型

public class UserController01 {
    @Resource(name = "user_2")
    private User user;

    public void doUserController01() {
        System.out.println("user Controller01.");
        System.out.println();
        System.out.println(user);
    }
}

使用 @Autowired注解和 @Qualifier注解

单独使用@Autowired注解是不能解决这个问题的,我们还要在搭配使用 @Qualifier注解来指定查找id名称是什么的bean对象。

@Qualifier注解的作用:用来指定查找id名称是多少的bean对象,@Qualifier注解里面只有一个参数,用来设置用来指定查找id名称Spring更简单保存和获取bean对象的方法(注解)_第13张图片

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

    public void doUserController01() {
        System.out.println("user Controller01.");
        System.out.println();
        System.out.println(user);
    }
}

注意:@Qualifier注解要搭配 @Autowired注解使用,自己单独使用没有效果

你可能感兴趣的:(笔记,spring,java,后端)