SpringBoot:详解依赖注入和使用配置文件

这篇具有很好参考价值的文章主要介绍了SpringBoot:详解依赖注入和使用配置文件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

SpringBoot:详解依赖注入和使用配置文件,# 深入浅出SpringBoot,spring boot,后端,java,依赖注入,软件工程

🏡浩泽学编程:个人主页

 🔥 推荐专栏:《深入浅出SpringBoot》《java项目分享》
              《RabbitMQ》《Spring》《SpringMVC》
🛸学无止境,不骄不躁,知行合一

前言

在上一篇文章中,讲诉了SpringIoC的Bean装配,但是对于如何进行获取,也就是Bean之间的依赖还未讲诉,下面开始讲诉依赖注入(Dependency Injection,DI)以及如何使用属性文件。涉及主要注解@Autowired、@Primary、@Quelifier、@PropertySource和@ConfigurationProperties。


一、🌕依赖注入

例:人类(Person)有时候利用一些动物(Animal)去完成一些事情,比方说狗(Dog)是用来看门的,猫(Cat)是用来抓老鼠的, 鹦鹉(Paηot)是用来迎客的……于是做一些事情就依赖于那些可爱的动物。假设现在需要用狗狗来看门。

//定义人类接口
public interface Person {
    void service();

    void setAnimal(Animal animal);
}
//定义动物接口
public interface Animal {
    void user();
}
//定义狗
@Component
public class Dog implements Animal {
    @Override
    public void user() {
        System.out.println("狗【" + Dog.class.getSimpleName() + "】是用来看门的");
    }
}
//定义年轻人
@Component
public class YoungPerson implements Person {
    @Autowired
    private Animal animal = null;

    @Override
    public void service() {
        this.animal.user();
    }

    @Override
    public void setAnimal(Animal animal) {
        this.animal = animal;
    }
}
//定义配置类
@Configuration
@ComponentScan("com.dragon.restart")//所有的包和类都在restart下
public class AppConfig {
}

测试类:

ApplicationContext ctx =new AnnotationConfigApplicationContext(AppConfig.class) ;
		Person person= ctx.getBean(YoungPerson.class) ;
		person.service() ;

SpringBoot:详解依赖注入和使用配置文件,# 深入浅出SpringBoot,spring boot,后端,java,依赖注入,软件工程
测试是成功的,这个时候SpringIoC 容器己经通过注解@Autowired成功地将Dog注入到了 YoungPerson 实例中。 但是这只是一个比较简单的例子,我们有必要继续探讨@Autowired。

🌖注解@Autowired

@Autowired 是我们使用得最多的注解之一, 因此在这里需要进一步地探讨它。 它注入的机制最基本的一条是根据类型 (bytype), 我们回顾IoC 容器的顶级接口 BeanFactory,就可以知道 IoC 容器是通过getBean 方法获取对应Bean 的,而 getBean 又支持根据类型(by type)或者根据名称(by name)。这里明显根据类型注入,将狗狗实例注入Animal对象。
再回到上面的例子,我们只是创建了一个动物一一狗,而实际上动物还可以有猫 (Cat),猫可以为我们抓老鼠, 于是我们又创建了一个猫的类。

@Component
public class Cat implements Animal{
    @Override
    public void user() {
        System.out.println("猫【" + Cat.class.getSimpleName() + "】是抓老鼠的");
    }
}

好了,如果我们还使用着YoungPerson类,那么麻烦来了,因为这个类只是定义了一个动物属性(Animal),而我们却有两个动物,一个狗, 一个猫, SpringIoC 如何注入呢?
运行测试,可以看到IoC容器抛出异常,如下:

Description:
Field animal in com.dragon.restart.pojo.impl.YoungPerson required a single bean, but 2 were found:
	- cat: defined in file [E:\IDEA_projects\restart\target\classes\com\dragon\restart\pojo\Cat.class]
	- dog: defined in file [E:\IDEA_projects\restart\target\classes\com\dragon\restart\pojo\impl\Dog.class]

那么使用@Autowired 能处理这个问题吗?答案是肯定的。假设我们目前需要的是狗提供服务,那么可以把属性名称转化为dog,也就是原来YoungPerson的private Animal animal = null; 改为private An工mal dog = null;

@Component
public class YoungPerson implements Person {
    @Autowired
    private Animal dog = null;

    @Override
    public void service() {
        this.dog.user();
    }

    @Override
    public void setAnimal(Animal animal) {
        this.dog = animal;
    }
}

这里, 我们只是将属性的名称从animal 修改为了 dog,那么我们再测试的时候,你可以看到是采用狗来提供服务的。那是因为@Autowired提供这样的规则:首先它会根据类型找到对应的Bean,如果对应类型的 Bean 不是唯一的,那么它会根据其属性名称和 Bean 的名称进行匹配。如果匹配得上,就会使用该Bean:如果还无法匹配,就会抛出异常。这里还要注意的是@Autowired 是一个默认必须找到对应 Bean 的注解,如果不能确定其标注属性一定会存在并且允许这个被标注的属性为null, 那么你可以配置@Autowired属性 required 为 false@Autowired(required = false)

@Autowired除了可以标注属性外,还可以标注方法, 如setAnimal方法,如下所示:

@Override
@Autowired 
public void setAnimal (Animal animal) { 
this.animal = animal;

这样它也会使用setAnimal 方法从 IoC 容器中找到对应的动物进行注入,甚至我们还可以使用在方法的参数上,后续文章会再谈到它。

🌗消除歧义性——@Quelifier和@Primary

在上面我们发现有猫有狗的时候, 为了使@Autowired 能够继续使用,我们做了一个决定,将YoungPerson 的属性名称从 animal 修改为 dog。显然这是一个憋屈的做法,好好的一个动物,却被我们定义为了狗,毕竟不能每次换个对象就改一次,这样太麻烦了。产生注入失败的问题根本是按类型(bytype) 查找, 正如动物可以有多种类型,这样会造成 Spring IoC 容器注入的困扰,我们把这样的一个问题称为歧义性。知道这个原因后, 那么这两个注解是从哪个角度去解决这些问题的呢?

首先是一个注解@Primary,它是一个修改优先权的注解,当我们有猫有狗的时候,假设这次需要使用猫, 那么只需要在猫类的定义上加入@Primarγ就可以了,如下:

@Component
@Primary
public class Dog implements Animal {
    @Override
    public void user() {
        System.out.println("狗【" + Dog.class.getSimpleName() + "】是用来看门的");
    }
}

这里的@Primary 的含义告诉 Spring IoC 容器, 当发现有多个同样类型的 Bean 时,请优先使用我进行注入,于是再进行测试时会发现,系统将用狗狗为你提供服务。 因为当 Spring 进行注入的时候,虽然它发现存在多个动物, 但因为Dog被标注为了@Primarγ,所以优先采用Dog的实例进行了注入,这样就通过优先级的变换使得IoC容器知道注入哪个具体的实例来满足依赖注入。然后,有时候@Primary 也可以使用在多个类上,也许无论是猫还是狗狗都可能带上@Primary 注解, 其结果是IoC容器还是无法区分采用哪个Bean的实例进行注入, 又或者说我们需要更加灵活的机制来实现注入,那么**@Quelifier** 可以满足你的这个愿望。

它将与@Autowired 组合在一起,通过类型和名称一起找到Bean。我们知道Bean 名称在 Spring IoC 容器中是唯一的标识,通过这个就可以消除歧义性了。此时你是否想起了BeanFactory接口中的这个方法呢?<T> T getBean(String name, Class<T> requiredType) throws BeansException;

代码:

@Component
public class YoungPerson implements Person {
    @Autowired
    @Qualifier("dog")
    private Animal animal = null;

    @Override
    public void service() {
        this.animal.user();
    }

    @Override
    public void setAnimal(Animal animal) {
        this.animal = animal;
    }
}

一旦这样声明, Spring IoC 将会以类型和名称去寻找对应的Bean进行注入。根据类型和名称,显然也只能找到狗狗为我们服务了。

🌑带有参数的构造方法类装配

在上面,我们都基于一个默认的情况,那就是不带参数的构造方法下实现依赖注入。但事实上,有些类只有带有参数的构造方法,于是上述的方法都不能再使用了。为了满足这个功能,我们可以使用@Autowired 注解对构造方法的参数进行注入,例如,修改类YoungPerson来满足这个功能。

@Component
public class YoungPerson implements Person {
    private Animal animal = null;

    public YoungPerson(@Autowired @Qualifier("dog") Animal animal) {
        this.animal = animal;
    }

    @Override
    public void service() {
        this.animal.user();
    }

    @Override
    public void setAnimal(Animal animal) {
        this.animal = animal;
    }
}

@Autowired 和@Qualifier 注解,使其注入进来。这里使用@Qualifier 是为了避免歧义性。当然如果你的环境中不是有猫有狗,则可以完全不使用@Qualifier,而单单使用@Autowired就可以了。

二、📝使用属性文件

Java 开发使用属性文件已经十分普遍,所以这里谈谈这方面的内容。在Spring Boot 中使用属性文件,可以采用其默认为我们准备的application.properties,也可以使用自定义的配置文件。 应该说读取配置文件的方法很多, 这里没有必要面面俱到地介绍每一个细节,只是介绍那些最常用的方法。

在SpringBoot项目的application.properties:

database.driverName=com.mysql.jdbc.Driver
database.url=jdbc:mysql://localhost:3306/my
database.username=root
database.password=root

创建个DataBaseProperties类:

/**
 * @Version: 1.0.0
 * @Author: Dragon_王
 * @ClassName: DataBaseProperties
 * @Description: TODO描述
 * @Date: 2024/1/16 16:07
 */
@Component
public class DataBaseProperties {
    @Value("${database.driverName}")
    private String driverName = null;
    @Value("${database.url}")
    private String url = null;
    private String username = null;
    private String password = null;

    public void setDriverName(String driverName) {
        System.out.println(driverName);
        this.driverName = driverName;
    }

    public void setUrl(String url) {
        System.out.println(url);
        this.url = url;
    }

    @Value("${database.username}")
    public void setUsername(String username) {
        System.out.println(username);
        this.username = username;
    }

    @Value("${database.password}")
    public void setPassword(String password) {
        System.out.println(password);
        this.password = password;
    }

    public String getDriverName() {
        return driverName;
    }

    public String getUrl() {
        return url;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }
}

通过@Value注解, 使用${… }这样的占位符读取配置在属性文件的内容。这里的@Value 注解,既可以加载属性, 也可以加在方法上。
这样就能成功将属性文件内容成功注入了。但是我们可以使用过注解@ConfigurationProperties来简化一下,同样能实现注入,如下:

/**
 * @Version: 1.0.0
 * @Author: Dragon_王
 * @ClassName: DataBaseProperties
 * @Description: TODO描述
 * @Date: 2024/1/16 16:07
 */
@Component
@ConfigurationProperties("database")
public class DataBaseProperties {
    private String driverName = null;
    private String url = null;
    private String username = null;
    private String password = null;

    public void setDriverName(String driverName) {
        System.out.println(driverName);
        this.driverName = driverName;
    }

    public void setUrl(String url) {
        System.out.println(url);
        this.url = url;
    }

    public void setUsername(String username) {
        System.out.println(username);
        this.username = username;
    }

    public void setPassword(String password) {
        System.out.println(password);
        this.password = password;
    }

    public String getDriverName() {
        return driverName;
    }

    public String getUrl() {
        return url;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }
}

这里@ConfigurationProperties注解内的database将会与属性名组成属性的全限定名去配置文件里查找,如属性driveName就会和database组成database.driverName去查找,这里注意一下不需要管字母的大小写,不影响。

如果我不用默认的application.properties文件怎么办呢?现在我们重新创建一个jdbc.properties文件,将原配置文件内容移入其中。
DataBaseProperties 类不变如上,启动类配置如下:

@SpringBootApplication
@PropertySource(value = {"classpath:jdbc.properties"},ignoreResourceNotFound = true)
public class RestartApplication {
	public static void main(String[] args) {
		SpringApplication.run(RestartApplication.class, args);
	}

}

SpringBoot:详解依赖注入和使用配置文件,# 深入浅出SpringBoot,spring boot,后端,java,依赖注入,软件工程
value 可以配置多个配置文件。使用 classpath 前缀, 意味着去类文件路径下找到属性文件;ignoreResourceNotFound 则是是否忽略配置文件找不到的问题。 ignoreResourceNotFound 的默认值为false,也就是没有找到属性文件, 就会报错;这里配置为true,也就是找不到就忽略掉,不会报错。通过运行日志,可以看出成功注入。


总结

以上就是依赖注入和使用配置配置文件的讲解,欢迎大家一起讨论。文章来源地址https://www.toymoban.com/news/detail-796293.html

到了这里,关于SpringBoot:详解依赖注入和使用配置文件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SpringBoot配置文件的注入和读取

    目录 1. 配置文件的作用 2. 两种配置文件的格式: 2.1 properties 基本语法: 2.1.1 写入 2.1.2 读取 执行原理 2.1.3 缺点分析 2.2 yml 基本语法: 2.2.1 写入(非对象) 2.2.3 配置对象 2.2.4 配置集合 多个配置文件         SpringBoot 是为了简化 Spring 的操作,提高 Spring 项目的开发效率,它

    2024年02月07日
    浏览(62)
  • springboot 注入配置文件中的集合 List

    在使用 springboot 开发时,例如你需要注入一个 url 白名单列表,你可能第一想到的写法是下面这样的: application.yml 然而,我们天真的以为,这样是没有问题的,实际不然, 这是一种错误的行为 ,本文截稿时 Spring 还是不支持直接使用 @Value 的方式注入集合的。 这种需求查看

    2024年02月05日
    浏览(35)
  • SpringBoot中的依赖注入和自动注入

    以下内容为本人学习 Spring Boot的依赖注入和自动注入 与ChatGpt提问后对其回答 进行部分修改 (有的错误实在是离谱 = =)、格式调整等操作后的答案, 可能对于其中部分细节(是错是对,能力有限有的看不出来 = =),并未做深入探究 ,大家感兴趣的话可以自行验证。 依赖注

    2024年02月06日
    浏览(75)
  • SpringBoot - 配置文件application.yml使用详解(附:Profile多环境配置)

    SpringBoot - 配置文件application.yml使用详解(附:Profile多环境配置) 1,基本介绍 (1)YAML 是 JSON 的超集,简洁而强大,是一种专门用来书写配置文件的语言,可以替代 application.properties。 (2)在创建一个 SpringBoot 项目时,引入的 spring-boot-starter-web 依赖间接地引入了 s

    2024年02月08日
    浏览(44)
  • Spring IOC:详解【依赖注入数值问题 & 依赖注入方式】

    编译软件:IntelliJ IDEA 2019.2.4 x64 操作系统:win10 x64 位 家庭版 Maven版本:apache-maven-3.6.3 Mybatis版本:3.5.6 spring版本:5.3.1 第一章:初识Spring:如何在Maven工程上搭建Spring框架? 第二章:Spring IOC:IOC在Spring底层中如何实现? 第三章:Spring IOC:详解【依赖注入数值问题 依赖注入

    2024年02月04日
    浏览(45)
  • 【SpringBoot】两种配置文件, 详解 properties 和 yml 的语法格式, 使用方式, 读取配置

    各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你: 📕 JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等 📗 Java数据结构: 顺序表, 链表, 堆, 二叉树, 二叉搜索树, 哈希表等 📘 JavaEE初阶: 多线程, 网络编程, TCP/IP协议, HTTP协议

    2024年02月10日
    浏览(52)
  • springboot依赖注入的三种方式

    springboot依赖注入的三种方式 在 Spring Boot 中,使用 XML 配置依赖注入(DI)时,需要使用 bean 元素来定义 bean,并使用 property 元素来为 bean 的属性注入值或依赖对象。 以下是一个简单的示例: 在 src/main/resources 目录下创建 applicationContext.xml 文件。 在该文件中定义一个 testBean

    2023年04月23日
    浏览(43)
  • Spring 依赖注入详解

    目录 1、基于构造器的依赖注入 2、基于 Setter 方法的依赖注入 3、使用构造器注入还是 setter 方法注入? 4、依赖注入解析的过程 5、依赖注入的相关示例 // 依赖关系,指的就是对象之间的相互协作关系         依赖注入(DI)是一个过程,在这个过程中,对象仅通过构造函

    2024年02月06日
    浏览(47)
  • Springboot依赖注入Bean的三种方式,final+构造器注入Bean

    @Autowired注解的一大使用场景就是Field Injection。 通过Java的反射机制实现,所以private的成员也可以被注入具体的对象 优点 代码少,简洁明了。 新增依赖十分方便,不需要修改原有代码 缺点 容易出现空指针异常。Field 注入允许构建对象实例时依赖的对象为空,导致空指针异常

    2024年02月02日
    浏览(48)
  • Angular系列教程之依赖注入详解

    Angular作为一款流行的前端框架,提供了许多优秀的功能和特性,其中之一就是依赖注入(Dependency Injection)。依赖注入是一种设计模式,它允许我们在代码中以一种可扩展和可测试的方式添加和配置依赖关系。在Angular中,依赖注入被广泛应用于组件、服务、指令等场景,本文

    2024年01月17日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包