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



    我们介绍了通过配置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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

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

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

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

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

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

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

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

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

    示例截图:
    在这里插入图片描述

    为什么要这么多类注解?

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

    的⽤途,⽐如:

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

    @Service:服务层;

    @Repository:持久层

    @Configuration:配置层

    程序的⼯程分层,调⽤流程如下:
    在这里插入图片描述

    类注解之间的关系

    查看 @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名
    在这里插入图片描述
    【程序员可以直接设置bean对象的id名】

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

    <1>

    @bean(name="id名字")
    
    • 1

    在这里插入图片描述
    <2>

    @Bean(value = "id名字")
    
    • 1

    在这里插入图片描述
    <3>

    @Bean("id名字")
    
    • 1

    在这里插入图片描述
    <4>一个bean对象可以设置多个id名称

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

    在这里插入图片描述

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

    在这里插入图片描述

    获取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();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    属性注入的有缺点

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

    缺点:

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

    setter注入

    在要依赖注入的类中写一个set方法,在set方法前加上@Autowired注解就行
    在这里插入图片描述

    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    构造方法注入的注意事项

    <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();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    <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();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    @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();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

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

    在这里插入图片描述
    我们能很清楚的看到,@Resource注解放到构造方法前就直接报错了

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

    相同点:

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

    不同点:

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

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

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

    3. 支持的参数不同

      @Resource注解里面可以设置很多种参数,而@Autowired注解只能设置一种参数
      在这里插入图片描述
      依赖查找的顺序不同

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

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

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

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

    我们在使用@Bean方法注解或者使用xml配置的方法来将对象保存到Spring容器中的时候,很有可以会出现有比较多类型相同,但是bean对象的id名称不同 的情况。我们在使用注解进行对象注入的时候会比较容易出现一下的异常
    在这里插入图片描述
    意思就是:找到了几个符合类型的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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    使用 @Autowired注解和 @Qualifier注解

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

    @Qualifier注解的作用:用来指定查找id名称是多少的bean对象,@Qualifier注解里面只有一个参数,用来设置用来指定查找id名称在这里插入图片描述

    @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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

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

  • 相关阅读:
    K8S知识点(九)
    深入理解JVM(十九)使用javap指令解析Class文件
    手机备忘录如何批量导出来,备忘录整体导出方法介绍
    Verilog刷题[hdlbits] :Always nolatches
    Flutter 3.0升级内容,该如何与小程序结合
    区块链侧链技术(0)——衍生知识补充
    无法安装64位版本的office,因为在您的PC上找到以下32位程序
    Mini Homer——几百块钱也能搞到一台远距离图数传链路?
    分库分表(2)——动态数据源实践
    工业产品外观设计的4个关键因素,你知道吗?
  • 原文地址:https://blog.csdn.net/weixin_62877993/article/details/127843511