【Spring进阶系列丨第五篇】详解Spring中的依赖注入

这篇具有很好参考价值的文章主要介绍了【Spring进阶系列丨第五篇】详解Spring中的依赖注入。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【Spring进阶系列丨第五篇】详解Spring中的依赖注入,Spring进阶系列,spring,数据库,java,spring boot,后端

一、说明

  • 全称

    Dependency Injection(DI)

  • 与IoC的关系

IoC和DI其实说的是一个意思,可以这么说:IoC是一种思想,DI是对这种思想的一种具体实现

  • 依赖关系的管理

以后都交给spring来维护,在当前类需要用到其他类的对象,由spring为我们提供,我们只需要在配置文件中说明。

  • 依赖关系的维护

    ​ 称之为依赖注入。

  • 能注入的数据:有三类

    ​ 基本类型和String。

    ​ 其他bean类型(在配置文件中或者注解配置过的bean)

    ​ 复杂类型/集合类型

  • 注入的方式:有三种

    ​ 第一种:使用构造函数提供

    ​ 第二种:使用set方法提供

    ​ 第三种:使用注解提供(参考第七章节)

二、构造函数注入

2.1、方式一【index索引方式】

2.1.1、定义Bean

public class Person {
    
    private Integer id;
    
    private String name;	// 姓名
    
    private Integer age;	// 年龄
  
  	private Double weight;	// 体重

    public Person(Integer id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
}

2.1.2、主配置文件中配置Bean

<beans>    
	<bean id="person" class="cn.bdqn.Person">
        <constructor-arg index="0" value="1" />
        <constructor-arg index="1" value="王浩"/>
        <constructor-arg index="2" value="20"/>
    </bean>
</beans>

2.1.3、测试

@Test
public void testPerson() throws Exception{
    // 1、读取主配置文件信息,获取核心容器对象
    ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");

    Person person = (Person) ac.getBean("person");

    System.out.println(person);	// Person{id=1, name='王浩', age=20}
}

2.2、方式二【index+type组合方式】

说明:案例1采用的index索引的方式实现注入,就以目前案例来说是完全没问题的,但是如果Bean中存在下面情况,可能就不怎么适用了。

需求:我现在要创建Person类的对象,调用Person(Integer id, String name, Double weight)构造方法

2.2.1、定义Bean

说明:为Person类中的weight属性初始化,并专门为其添加构造方法

public class Person {

    private Integer id;

    private String name;    // 姓名

    private Integer age;    // 年龄

    private Double weight;  // 体重

    public Person(Integer id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

  	// 专门为weight属性定义的构造方法
    public Person(Integer id, String name, Double weight) {
        this.id = id;
        this.name = name;
        this.weight = weight;
    }
}

2.2.2、主配置文件配置Bean

<beans>    
	<bean id="person" class="cn.bdqn.Person">
        <constructor-arg index="0" value="1" />
        <constructor-arg index="1" value="王浩"/>
        <constructor-arg index="2" value="180"/>
    </bean>
</beans>

2.2.3、测试

@Test
public void testPerson() throws Exception{
    // 1、读取主配置文件信息,获取核心容器对象
    ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");

    Person person = (Person) ac.getBean("person");

    System.out.println(person);	// Person{id=1, name='王浩', age=180}
}

经过测试发现,并不满足我的需求,还是找的是public Person(Integer id, String name, Integer age)构造方法

2.2.4、解决方案

通过type明确指定类型。

<bean>
  	<bean id="person" class="cn.bdqn.Person">
        <constructor-arg index="0" type="java.lang.Integer" value="1" />
        <constructor-arg index="1" type="java.lang.String" value="王浩"/>
        <constructor-arg index="2" type="java.lang.Double" value="180"/>
    </bean>
</bean>

2.3、方式三【name方式】

前两种方式通过index+type的确可以解决问题,但是总是觉得还是有些麻烦,能否有更加简单的方式呢?就是直接采用参数名的方式更易于阅读和使用。

2.3.1、定义Bean

​ Bean的定义同2.2.1。

2.3.2、主配置文件配置Bean

<beans>
	  <bean id="person" class="cn.bdqn.Person">
        <constructor-arg name="id" value="2"/>
        <constructor-arg name="name" value="史周冲"/>
        <constructor-arg name="age" value="3"/>
    </bean>
</beans>

2.3.3、测试

@Test
public void testPerson() throws Exception{
        // 1、读取主配置文件信息,获取核心容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");

        Person person = (Person) ac.getBean("person");

        System.out.println(person);	// Person{id=1, name='王浩', age=3}
}

2.4、补充细节

2.4.1、定义Bean

public class Person {

    private Integer id;

    private String name;    // 姓名
    
    private Date birthday;  // 出生日期

    public Person(Integer id, String name, Date birthday) {
        this.id = id;
        this.name = name;
        this.birthday = birthday;
    }
}

2.4.2、主配置文件配置Bean

<beans>
  	 <bean id="person" class="cn.bdqn.Person">
        <constructor-arg name="id" value="2"/>
        <constructor-arg name="name" value="史周冲"/>
        <constructor-arg name="birthday" value="2019-09-09" />
    </bean>
</beans>

2.4.3、测试

测试后发现程序报错,原因在于:期望需要一个Date类型,而你现在传了一个字符串,数据类型不匹配。

Unsatisfied dependency expressed through constructor parameter 2: Could not convert argument value of type [java.lang.String] to required type [java.util.Date]

2.4.4、解决方案

<beans>
  	<bean id="person" class="cn.bdqn.Person">
        <constructor-arg name="id" value="2"/>
        <constructor-arg name="name" value="史周冲"/>
      	<!-- 注意:用了ref属性-->
        <constructor-arg name="birthday" ref="currentDate"/>
    </bean>
	
  	<!-- 定义日期Bean,Spring就会帮助我们new一个Date对象-->
    <bean id="currentDate" class="java.util.Date"/>
</beans>

2.5、总结

  • 使用的标签:

    ​ constructor-arg

  • 标签出现的位置:

    ​ bean标签的内部

  • 标签中的属性:

    ​ type:用于指定要注入的数据的数据类型。

    ​ index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值,索引的位置是从0开始。

    ​ name:用于指定给构造函数中指定名称的参数赋值。

    ​ value:用于提供基本类型和String类型的数据。

    ref:引用,用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象。

  • 优势:

    ​ 假设我们需要创建一个对象时,需要明确初始化一些数据,那么这种方式显然是很好的。因为通过构造函数创建对象时候,如果不指定具体的参数是无法把对象创建成功的。可以起到一个约束的作用。

  • 劣势:

    ​ 改变了bean对象的实例化方式,使我们在创建对象时,如果用不到这些数据,也必须提供。

三、set方法注入

3.1、定义Bean

public class User {

    private String name;

    private Date born;

    public void setName(String name) {
        this.name = name;
    }

    public void setBorn(Date born) {
        this.born = born;
    }
}

说明:set注入方式不必生成get方法

3.2、主配置文件配置Bean

<bean id="currentDate" class="java.util.Date"/>
    
<bean id="user" class="cn.bdqn.User">
    <property name="name" value="宋炜烨"/>
    <property name="born" ref="currentDate"/>
</bean>

3.3、测试

@Test
public void testUser() throws Exception{
        // 1、读取主配置文件信息,获取核心容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");

        User user = (User) ac.getBean("user");

        System.out.println(user);	// User{name='宋炜烨', born=Thu Nov 14 22:29:11 CST 2019}
}

3.4、总结

  • 涉及的标签

    ​ property

  • 出现的位置

    ​ bean标签的内部

  • 标签的属性

    ​ name:用于指定注入时所调用的set方法名称。

    ​ value:用于提供基本类型和String类型的数据。

    ​ ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象。

  • 优势

    ​ 创建对象时没有明确的限制,可以直接使用默认构造函数。

  • 劣势

    ​ 如果有某个成员属性必须有值,则有可能再使用该对象的时候并没有通过set方法注入值,可能拿到为空的值。

四、复杂类型的注入

4.1、注入数组类型【array】

4.1.1、定义Bean

public class Cat {
    
    private String[] arrs;

    public void setArrs(String[] arrs) {
        this.arrs = arrs;
    }
}

4.1.2、主配置文件配置Bean

<beans>
  <bean id="cat" class="cn.bdqn.Cat">
          <property name="arrs">
              <array>
                  <value>崔灿</value>
                  <value>时贝妮</value>
              </array>
          </property>
  </bean>
</beans>

4.2、注入List类型【list】

4.2.1、定义Bean

public class Cat {

    private List<String> arrList;

    public void setArrList(List<String> arrList) {
        this.arrList = arrList;
    }
}

4.2.2、主配置文件配置Bean

<beans>
	 <bean id="cat" class="cn.bdqn.Cat">
        <property name="arrList">
            <list>
                <value>乔峰</value>
                <value>马夫人</value>
            </list>
        </property>
    </bean>
</beans>

4.3、注入Set类型【set】

4.3.1、定义Bean

public class Cat {

    private Set<String> arrSet;

    public void setArrSet(Set<String> arrSet) {
        this.arrSet = arrSet;
    }
}

4.3.2、主配置文件配置Bean

<beans>
	    <bean id="cat" class="cn.bdqn.Cat">
            <property name="arrSet">
                <set>
                    <value>段誉</value>
                    <value>鸠摩智</value>
                </set>
            </property>
   	 	</bean>
</beans>

4.4、注入Map类型【Map】

4.4.1、定义Bean

public class Cat {

    private Map<String,Object> arrMap;

    public void setArrMap(Map<String, Object> arrMap) {
        this.arrMap = arrMap;
    }
}

4.4.2、主配置文件配置Bean

<bean>
	<property name="arrMap">
        <map>
           	<entry key="S001" value="彭依凝"/>
            <entry key="S002" value="段康家"/>
            <entry key="S003" value="王浩"/>
        </map>
    </property>
</bean>

4.5、注入Properties类型

4.5.1、定义Bean

public class Cat {

    private Properties props;

    public void setProps(Properties props) {
        this.props = props;
    }
}

4.5.2、主配置文件配置Bean

<bean id="cat" class="cn.bdqn.Cat">
     <property name="props">
            <props>
                <prop key="A001">虚竹</prop>
                <prop key="A002">扫地僧</prop>
            </props>
     </property>
</bean>

4.6、总结

  • 用于给List结构集合注入的标签:

    ​ list、array、set

  • 用于个Map结构集合注入的标签:

    ​ map 、props

  • 总结

    结构相同,标签可以互换

好书推荐

【Spring进阶系列丨第五篇】详解Spring中的依赖注入,Spring进阶系列,spring,数据库,java,spring boot,后端
《Spring Batch权威指南》主要内容:

  • 探索Spring Batch 4中的新特性。

  • 使用Spring Batch项目在云环境中完成有限的批处理任务。

  • 通过一些示例,理解z新的基于Java和Spring Boot的配置技术

  • 掌握复杂场景和云环境中的批处理

  • 开发能够运行在现代平台上的批处理应用

  • 除了Spring Batch,使用Spring Portfolio的其他部分开发关键任务型批处理应用

购书链接:点此进入

送书活动

参与方式:点击进入参与 公平公正公开 人少好中奖!


【Spring进阶系列丨第五篇】详解Spring中的依赖注入,Spring进阶系列,spring,数据库,java,spring boot,后端文章来源地址https://www.toymoban.com/news/detail-759841.html

到了这里,关于【Spring进阶系列丨第五篇】详解Spring中的依赖注入的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 【Spring进阶系列丨第八篇】Spring整合junit & 面向切面编程(AOP)详解

    ​ @ContextConfiguration注解需要注意的细节是: classes:指定的是主配置类的字节码 locations:指定xml文件的位置 ​ 首先来看一个问题,假如我现在有一个UserServiceImpl用户业务类,其中呢,有一个保存用户的方法,即: ​ 现在的需求是:我要在保存用户之前新增事务的功能,你

    2024年04月13日
    浏览(43)
  • 【Spring进阶系列丨第十篇】基于注解的面向切面编程(AOP)详解

    ​ 注意,该类的两个细节: a、@Component注解向容器中注册一个Bean。 b、@Aspect注解表示这个是一个切面类。 c、@Before注解表示的是这个是前置增强/前置通知。 ​ 注意:对于业务Bean,我们也需要通过@Service注解来向容器中注册。 ​ 问题:我们看到对于切面类中定义的通知,有

    2024年04月23日
    浏览(38)
  • 【Spring进阶系列丨第九篇】基于XML的面向切面编程(AOP)详解

    1.1.1、beans.xml中添加aop的约束 1.1.2、定义Bean ​ 问题:我们上面的案例经过测试发现确实在调用业务方法之前增加了日志功能,但是问题是仅仅能针对某一个业务方法进行增强,而我们的业务方法又有可能有很多,所以显然一个一个的去配置很麻烦,如何更加灵活的去配置呢

    2024年04月18日
    浏览(42)
  • 【Spring进阶系列丨第一篇】初识Spring开发

    小伙伴们大家好,我是陈橘又青,今天起 《Spring进阶系列》 开始更新。本专栏将涵盖Spring框架的核心概念、配置管理、Web开发、AOP、Boot、Security、Data、Integration和Batch等多个主题。通过理论讲解和实际案例的剖析,帮助读者深入理解Spring框架的原理和应用技巧,提升开发人员

    2024年02月05日
    浏览(35)
  • 【Spring进阶系列丨第六篇】Spring的Bean管理(基于注解)

    回顾一下 基于xml配置的Spring对Bean的管理 ,对Bean的完整管理如下所示: 分析可以发现:我们对Bean的管理就四个方面,分别是: 用于创建对象的 用于注入数据的 用于改变Bean的作用域的 和Bean的生命周期相关的 其实对于注解来说,也是包括了这四个方面,换句话说, 使用注

    2024年02月03日
    浏览(42)
  • 【Spring进阶系列丨第三篇】Spring核心技术之 IoC 与 DI 实战案例

    在上一篇文章中,我们学习了IoC与DI的相关概念与原理,现在让我们 以HelloWorld为例,编写一个程序,让创建对象的工作由Spring帮助我们创建。 一同感受一下Spring框架带给我们开发的便捷性。 这种做法是以前最常用的做法,HelloWorld这个类的对象是我们程序员自己去创建并为属

    2024年02月05日
    浏览(40)
  • 详解TCP/IP协议第五篇:详细介绍网络传输中的地址

    😉😉 学习交流群: ✅✅1:这是孙哥suns给大家的福利! ✨✨2:我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 🥭🥭3:QQ群:583783824   📚📚  工作微信:BigTreeJava 拉你进微信群,免费领取! 🍎🍎4:本文章内容出自上述:Spring应用课程!💞💞

    2024年02月07日
    浏览(29)
  • 【Spring进阶系列丨最终篇】一文详解Spring中的事务控制

    本篇文章是【Spring进阶系列】专栏的最后一篇文章,至此,我们对Spring的学习就告一段落,接下来我会持续更新【 Spring+SpringMVC+MyBatis整合 】专栏,欢迎免费订阅! 事务需要放在业务层(service) Spring的事务是基于AOP的 Spring的事务控制有两种:编程式事务【了解】和 声明式事务

    2024年04月25日
    浏览(25)
  • Vue系列第五篇:Vue2(Element UI) + Go(gin框架) + nginx开发登录页面及其校验登录功能

       本篇使用Vue2开发前端,Go语言开发服务端,使用nginx代理部署实现登录页面及其校验功能。 目录 1.部署结构 2.Vue2前端 2.1代码结构 2.1源码 3.Go后台服务 3.2代码结构 3.2 源码 3.3单测效果 4.nginx 5.运行效果 6.问题总结   index.html !DOCTYPE html html   head     meta charset=\\\"utf-8\\\"     m

    2024年02月15日
    浏览(42)
  • 【boost网络库从青铜到王者】第五篇:asio网络编程中的同步读写的客户端和服务器示例

    前面我们介绍了 boost::asio 同步读写的 api 函数,现在将前面的 api 串联起来,做一个能跑起来的 客户端 和 服务器 。 客户端 和 服务器 采用阻塞的同步读写方式完成通信。 客户端设计基本思路是根据服务器对端的 ip和端口 创建一个 endpoint ,然后创建 socket 连接这个 endpoint

    2024年02月12日
    浏览(30)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包