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

SpringBoot

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

SpringBoot 原理篇

文章目录

      • SpringBoot
      • SpringBoot 原理篇
      • 1 自动配置
        • 1.13 bean 依赖属性配置
          • 1.13.1 环境准备
          • 1.13.2 bean 依赖属性配置
          • 1.13.3 小结

1 自动配置

1.13 bean 依赖属性配置

1.13.1 环境准备

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

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第1张图片

直接创建

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第2张图片

OK, 一个全新的Maven 工程

【添加坐标】

<dependencies>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starterartifactId>
        <version>2.7.4version>
    dependency>
dependencies>

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第3张图片

OK

【实体类】

package com.dingjiaxiong.bean;

/**
 * ClassName: Cat
 * date: 2022/10/25 13:03
 *
 * @author DingJiaxiong
 */
public class Cat {
}
package com.dingjiaxiong.bean;

/**
 * ClassName: Mouse
 * date: 2022/10/25 13:03
 *
 * @author DingJiaxiong
 */

public class Mouse {
}

【运行类】

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);

        

    }

}

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打起来了");
    }

}

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();
    }

}

OK,直接运行

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第4张图片

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

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

先导一个lombok

<dependency>
    <groupId>org.projectlombokgroupId>
    <artifactId>lombokartifactId>
    <version>1.18.24version>
dependency>

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第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;

}
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;

}

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() + "打起来了");
    }

}

OK,直接运行

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第6张图片

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

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

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第7张图片

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

先来一个配置文件

cartoon:
  cat:
    name: tom
    age: 3

  mouse:
    name: jerry
    age: 4

在业务中读取值

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() + "打起来了");
    }

}

直接运行

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第8张图片

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

修改一下配置文件

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第9张图片

OK, 数据也正常替换了

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

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第10张图片

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

而且现在的问题是

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第11张图片

现在这个类已经绑死了 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;

}

之前的去使用这个属性类

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() + "打起来了");
    }

}

先直接打印看看,

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第12张图片

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

改一下

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

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

直接运行

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第13张图片

OK, 没毛病

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

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第14张图片

就还是tom

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

现在我把整个猫都拿掉

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

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

OK,再次运行

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第15张图片

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

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第16张图片

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() + "打起来了");
    }

}

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

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第17张图片

去掉一个单一属性

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第18张图片

就是这样

整个猫都拿掉

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第19张图片

如果全部拿掉

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第20张图片

没毛病

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

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第21张图片

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

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第22张图片

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

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

如果直接删掉这个注解

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第23张图片

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

【解决办法】

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第24张图片

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

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

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第25张图片

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

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第26张图片

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

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第27张图片

这样达到的效果就是

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第28张图片

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

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

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第29张图片

没毛病

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

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第30张图片

就能用了

做了这么多步骤:

核心:

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

OK,回顾一下

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

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第31张图片

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

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第32张图片

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

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第33张图片

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

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置_第34张图片

1.13.3 小结
  1. 业务bean的属性可以为其设定默认值
  2. 当需要设置时通过配置文件传递属性
  3. 业务bean应尽量避免设置强制加载,而是根据需要导入后加载,降低spring容器管理bean的强度

你可能感兴趣的:(SpringBoot2,spring,boot,java,spring)