• SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置


    SpringBoot

    【黑马程序员SpringBoot2全套视频教程,springboot零基础到项目实战(spring boot2完整版)】

    SpringBoot 原理篇

    1 自动配置

    1.13 bean 依赖属性配置
    1.13.1 环境准备

    创建一个全新的Maven 工程模块

    在这里插入图片描述

    直接创建

    在这里插入图片描述

    OK, 一个全新的Maven 工程

    【添加坐标】

    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starterartifactId>
            <version>2.7.4version>
        dependency>
    dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    OK

    【实体类】

    package com.dingjiaxiong.bean;
    
    /**
     * ClassName: Cat
     * date: 2022/10/25 13:03
     *
     * @author DingJiaxiong
     */
    public class Cat {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    package com.dingjiaxiong.bean;
    
    /**
     * ClassName: Mouse
     * date: 2022/10/25 13:03
     *
     * @author DingJiaxiong
     */
    
    public class Mouse {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    【运行类】

    package com.dingjiaxiong;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    
    /**
     * ClassName: App
     * date: 2022/10/25 13:03
     *
     * @author DingJiaxiong
     */
    
    @SpringBootApplication
    public class App {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext context = SpringApplication.run(App.class);
    
            
    
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    OK, 基本环境就准备好了

    1.13.2 bean 依赖属性配置

    来一个业务层【拍猫和老鼠的动画片】

    package com.dingjiaxiong.bean;
    
    import org.springframework.stereotype.Component;
    
    /**
     * ClassName: CartoonCatAndMouse
     * date: 2022/10/25 13:06
     *
     * @author DingJiaxiong
     */
    
    @Component
    public class CartoonCatAndMouse {
    
        private Cat cat;
        private Mouse mouse;
    
        public void play(){
            System.out.println("3岁的tom和4岁的jerry打起来了");
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    OK, 在运行程序中获取这个bean

    package com.dingjiaxiong;
    
    import com.dingjiaxiong.bean.CartoonCatAndMouse;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    
    /**
     * ClassName: App
     * date: 2022/10/25 13:03
     *
     * @author DingJiaxiong
     */
    
    @SpringBootApplication
    public class App {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext context = SpringApplication.run(App.class);
    
            CartoonCatAndMouse bean = context.getBean(CartoonCatAndMouse.class);
            bean.play();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    OK,直接运行

    在这里插入图片描述

    没啥问题,现在就是一个调用打印

    现在的问题就是这句打印的数据都是一个字符串写死的,所以要换

    先导一个lombok

    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
        <version>1.18.24version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    修改实体类

    package com.dingjiaxiong.bean;
    
    import lombok.Data;
    
    /**
     * ClassName: Cat
     * date: 2022/10/25 13:03
     *
     * @author DingJiaxiong
     */
    
    @Data
    public class Cat {
    
        private String name;
        private Integer age;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    package com.dingjiaxiong.bean;
    
    import lombok.Data;
    
    /**
     * ClassName: Mouse
     * date: 2022/10/25 13:03
     *
     * @author DingJiaxiong
     */
    
    @Data
    public class Mouse {
    
        private String name;
        private Integer age;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    OK,现在属性都有了

    修改业务代码

    package com.dingjiaxiong.bean;
    
    import org.springframework.stereotype.Component;
    
    /**
     * ClassName: CartoonCatAndMouse
     * date: 2022/10/25 13:06
     *
     * @author DingJiaxiong
     */
    
    @Component
    public class CartoonCatAndMouse {
    
        private Cat cat;
        private Mouse mouse;
    
        public CartoonCatAndMouse() {
            cat = new Cat();
            cat.setName("tom");
            cat.setAge(3);
    
            mouse = new Mouse();
            mouse.setName("jerry");
            mouse.setAge(4);
        }
    
        public void play(){
            System.out.println(cat.getAge() + "岁的" + cat.getName() + "和" + mouse.getAge() + "岁的" + mouse.getName() + "打起来了");
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    OK,直接运行

    在这里插入图片描述

    这样就不是写死的数据了而且实现相同的效果

    现在问题就是,当前这样子写,如果想正常运行

    在这里插入图片描述

    这些数据必须得告诉程序,但是如果有一天猫或者老鼠出意外了,导致咱们必须从外部修改这些“演员”,怎么做?

    先来一个配置文件

    cartoon:
      cat:
        name: tom
        age: 3
    
      mouse:
        name: jerry
        age: 4
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在业务中读取值

    package com.dingjiaxiong.bean;
    
    import lombok.Data;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.stereotype.Component;
    
    /**
     * ClassName: CartoonCatAndMouse
     * date: 2022/10/25 13:06
     *
     * @author DingJiaxiong
     */
    
    @Component
    @Data
    @ConfigurationProperties(prefix = "cartoon")
    public class CartoonCatAndMouse {
    
        private Cat cat;
        private Mouse mouse;
    
        public void play(){
            System.out.println(cat.getAge() + "岁的" + cat.getName() + "和" + mouse.getAge() + "岁的" + mouse.getName() + "打起来了");
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    直接运行

    在这里插入图片描述

    可以看到, 这样子数据也上来了

    修改一下配置文件

    在这里插入图片描述

    OK, 数据也正常替换了

    但是如果我压根儿不给老鼠的数据

    在这里插入图片描述

    没给就导致业务中的mouse 没有初始化,然后又直接使用,就这样儿了

    而且现在的问题是

    在这里插入图片描述

    现在这个类已经绑死了 yml 中的数据,如果yml 不提供数据,这个类就没法儿用了【这好像也不太行,有解决办法吗?】

    答案是当然的

    先来一个全新的类

    package com.dingjiaxiong.bean;
    
    import lombok.Data;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.stereotype.Component;
    
    /**
     * ClassName: CartoonProperties
     * date: 2022/10/25 13:27
     *
     * @author DingJiaxiong
     */
    
    @Component
    @Data
    @ConfigurationProperties(prefix = "cartoon")
    public class CartoonProperties {
    
        private Cat cat;
        private Mouse mouse;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    之前的去使用这个属性类

    package com.dingjiaxiong.bean;
    
    import lombok.Data;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.stereotype.Component;
    
    /**
     * ClassName: CartoonCatAndMouse
     * date: 2022/10/25 13:06
     *
     * @author DingJiaxiong
     */
    
    @Component
    @Data
    
    public class CartoonCatAndMouse {
    
        private Cat cat;
        private Mouse mouse;
    
        private CartoonProperties cartoonProperties;
    
        public CartoonCatAndMouse(CartoonProperties cartoonProperties) {
            this.cartoonProperties = cartoonProperties;
            cat = new Cat();
            cat.setName("tom");
            cat.setAge(3);
    
            mouse = new Mouse();
            mouse.setName("jerry");
            mouse.setAge(4);
        }
    
        public void play(){
            System.out.println(cat.getAge() + "岁的" + cat.getName() + "和" + mouse.getAge() + "岁的" + mouse.getName() + "打起来了");
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    先直接打印看看,

    在这里插入图片描述

    说明现在这些值拿的还是本类构造方法中设置的值

    改一下

    cat.setName(StringUtils.hasText(cartoonProperties.getCat().getName()) ? cartoonProperties.getCat().getName() : "tom");
    
    • 1

    意思是如果属性类中有值,就用属性类的值对tom 进行覆盖

    直接运行

    在这里插入图片描述

    OK, 没毛病

    如果配置文件中没配猫的name

    在这里插入图片描述

    就还是tom

    现在达到的效果 就是如果配置里面设置 了新的,就用新的,如果没有,就用老的

    现在我把整个猫都拿掉

    在这里插入图片描述

    这样会报错,因为属性类中的cat 为空了,再去拿空的name 就报错了,所以要再加个条件

    cat.setName(cartoonProperties.getCat() != null && StringUtils.hasText(cartoonProperties.getCat().getName()) ? cartoonProperties.getCat().getName() : "tom");
    
    • 1

    OK,再次运行

    在这里插入图片描述

    这样就行了,现在我仅仅是把猫的名字注掉

    在这里插入图片描述

    OK, 还是可以用

    按照这种判断形式,完善一下业务代码

    package com.dingjiaxiong.bean;
    
    import lombok.Data;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.stereotype.Component;
    import org.springframework.util.StringUtils;
    
    /**
     * ClassName: CartoonCatAndMouse
     * date: 2022/10/25 13:06
     *
     * @author DingJiaxiong
     */
    
    @Component
    @Data
    
    public class CartoonCatAndMouse {
    
        private Cat cat;
        private Mouse mouse;
    
        private CartoonProperties cartoonProperties;
    
        public CartoonCatAndMouse(CartoonProperties cartoonProperties) {
            this.cartoonProperties = cartoonProperties;
            cat = new Cat();
            cat.setName(cartoonProperties.getCat() != null && StringUtils.hasText(cartoonProperties.getCat().getName()) ? cartoonProperties.getCat().getName() : "tom");
            cat.setAge(cartoonProperties.getCat() != null && cartoonProperties.getCat().getAge() != null ? cartoonProperties.getCat().getAge() : 3);
    
            mouse = new Mouse();
    
            mouse.setName(cartoonProperties.getMouse() != null && StringUtils.hasText(cartoonProperties.getMouse().getName()) ? cartoonProperties.getMouse().getName() : "jerry");
            mouse.setAge(cartoonProperties.getMouse() != null && cartoonProperties.getMouse().getAge() != null ? cartoonProperties.getMouse().getAge() : 4);
            
        }
    
        public void play(){
            System.out.println(cat.getAge() + "岁的" + cat.getName() + "和" + mouse.getAge() + "岁的" + mouse.getName() + "打起来了");
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    现在的效果,就是配置文件的值和属性中的值融合

    在这里插入图片描述

    去掉一个单一属性

    在这里插入图片描述

    就是这样

    整个猫都拿掉

    在这里插入图片描述

    如果全部拿掉

    在这里插入图片描述

    没毛病

    现在就没有在真正的动画片类中去强制和配置文件绑死了【通过一个属性类解耦了】

    在这里插入图片描述

    OK, 差不多就是这样 了,但还有个小问题,在属性类中

    在这里插入图片描述

    加上这个注解后,这个属性类最终肯定会被加载成 bean

    如果现在我们不用动画片那个业务类的了的话,这个属性类也就没有必要加载了

    如果直接删掉这个注解

    在这里插入图片描述

    可以看到,如果不是一个bean了,就不能读取配置文件中的数据了

    【解决办法】

    在这里插入图片描述

    这样就可以把它强制整个一个bean了

    OK, 这个问题解决了,顺带的问题又来了

    在这里插入图片描述

    这个类现在也一定会被加载成bean,好家伙,也拿掉?

    在这里插入图片描述

    拿掉之后,到运行类中使用@Import 进行加载

    在这里插入图片描述

    这样达到的效果就是

    在这里插入图片描述

    这两个东西现在都没有强制声明成bean 了

    【但是现在能用吗?试试】

    在这里插入图片描述

    没毛病

    现在的感觉就是在运行类中,导入这样一个功能,

    在这里插入图片描述

    就能用了

    做了这么多步骤:

    核心:

    • 现在我们可以“合理”的读取配置文件中的数据了,配了我就读,没配我就默认
    • 而且对于业务类和属性类,我都无需声明成bean,只需要在用的地方写清楚就行了

    OK,回顾一下

    将业务功能bean运行需要的资源抽取成独立的属性类(******Properties),设置读取配置文件信息

    在这里插入图片描述

    配置文件中使用固定格式为属性类注入数据

    在这里插入图片描述

    定义业务功能bean,通常使用@Import导入,解耦强制加载bean

    在这里插入图片描述

    使用@EnableConfigurationProperties注解设定使用属性类时加载bean

    在这里插入图片描述

    1.13.3 小结
    1. 业务bean的属性可以为其设定默认值
    2. 当需要设置时通过配置文件传递属性
    3. 业务bean应尽量避免设置强制加载,而是根据需要导入后加载,降低spring容器管理bean的强度
  • 相关阅读:
    第二十六章 源代码文件 REST API 参考(八)
    Redis 数据类型 list 以及使用场景
    vue中实现瀑布流布局
    类加载器源码分析-双亲委派机制
    C#以太网简介
    表单(非常非常重要)
    【原创】xenomai UDD介绍与UDD用户态驱动示例
    随机数生成器代码HTML5
    ElasticSearch学习篇10_Lucene数据存储之BKD动态磁盘树
    Eginx配置(SSL,令牌登录认证,IP白名单,代理转发)
  • 原文地址:https://blog.csdn.net/weixin_44226181/article/details/128049161