写点什么

Spring 之 DI 依赖注入

作者:楠羽
  • 2022 年 10 月 10 日
    福建
  • 本文字数:7530 字

    阅读完需:约 25 分钟

6、(DI)依赖注入

DI 与 IOC 的关系:


相同问题不同角度分析。



  • 名称:property

  • 类型:标签

  • 归属:bean 标签

  • 作用:使用 set 方法的形式为 bean 提供资源

  • 格式:


  <bean>    <property />  </bean>
复制代码


  • 基本属性:


  <property name="propertyName" value="propertyValue" ref="beanId"/>
复制代码


​ name:对应 bean 中的属性名,要求该属性必须提供可访问的 set 方法(严格规范为此名称是 set 方法对应名称)


​ value:设定非引用类型属性对应的值,不能与 ref 同时使用


​ ref:设定引用类型属性对应 bean 的 id ,不能与 value 同时使用


  • 注意:一个 bean 可以有多个 property 标签


<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans        https://www.springframework.org/schema/beans/spring-beans.xsd">    <!--1.创建spring控制的资源-->    <!--bean可以使用多个名称,使用那么属性完成,中间使用,隔开-->    <bean id="userService" name="userService1" class="com.DI.service.Impl.UserServiceImpl">        <!--3.将要租注入的引用类型的变量通过property属性进行注入,对应的name是要注入的变量名 使用ref属性声明要注入的bean的id-->        <property name="userDao" ref="userDao"/>        <property name="num" value="666"/>        <property name="version" value="楠木"/>    </bean>    <!--将要注入的资源声明为bean,引用类型需要声明,非引用类型的不用声明,直接赋值-->    <bean id="userDao" class="com.DI.service.Impl.UserDaoImpl"/></beans>
复制代码

6.1、构造器注入

  • 名称:constructor-arg

  • 类型:标签

  • 归属:bean 标签

  • 作用:使用构造方法的形式为 bean 提供资源,兼容早期遗留系统的升级工作

  • 格式:


  <bean>    <constructor-arg />  </bean>
复制代码


  • 基本属性:


  <constructor-arg name="argsName" value="argsValue />
复制代码


​ name:对应 bean 中的构造方法所携带的参数名


​ value:设定非引用类型构造方法参数对应的值,不能与 ref 同时使用


其他属性:


<constructor-arg index="arg-index" type="arg-type" ref="beanId"/>
复制代码


​ ref:设定引用类型构造方法参数对应 bean 的 id ,不能与 value 同时使用


​ type :设定构造方法参数的类型,用于按类型匹配参数或进行类型校验


​ index :设定构造方法参数的位置,用于按位置匹配参数,参数 index 值从 0 开始计数


  • 注意:一个 bean 可以有多个 constructor-arg 标签


<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans        https://www.springframework.org/schema/beans/spring-beans.xsd">    <!--将要注入的资源声明为bean,引用类型需要声明,非引用类型的不用声明,直接赋值-->    <bean id="userDao" class="com.DI.service.Impl.UserDaoImpl"/>        <bean id="userService" name="userService1" class="com.DI.service.Impl.UserServiceImpl">        <!--不加name,也可以加index:从0开始-->       <constructor-arg name="userDao" ref="userDao"/>        <constructor-arg name="num" value="66666"/>        <constructor-arg name="version" value="楠木"/>    </bean></beans>
复制代码

6.2、Set 方式注入【重点】

依赖注入:Set 注入!


  • 依赖:bean 对象的创建依赖于容器!

  • 注入: 上 bean 对象中的所有属性,由容器来注入!

【环境搭建】

1.复杂类型

package com.blue.pojo;
public class Address {
private String address;
public String getAddress() { return address; }
public void setAddress(String address) { this.address = address; }}
复制代码

2.真实测试对象

public class Student {
private String name; private Address address; private String[] books; private List<String> hobbies; private Map<String,String> card; private Set<String> games; private String wife; private Properties into;
复制代码


beans.xml


<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="student" class="com.blue.pojo.Student"> <!-- 第一种,普通注入,value --> <property name="name" value="blue"/> </bean></beans>
复制代码


MyTest


public class MyTest {    public static void main(String[] args) {        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");        Student student = (Student) context.getBean("student");        System.out.println(student.getName());    }}
复制代码

集合注入方式:

  • 名称:array,list,set,map,props

  • 类型:标签

  • 归属:property 标签 或 constructor-arg 标签

  • 作用:注入集合数据类型属性

  • 格式:


  <property>    <list></list>  </property>
复制代码


(1)集合类型数据注入——list


<property name="al">    <list>        <value>itheima</value>        <value>66666</value>    </list></property>
复制代码


(2)集合类型数据注入——props


<property name="properties">    <props>        <prop key="name">itheima666</prop>        <prop key="value">666666</prop>    </props></property>
复制代码


(3)集合类型数据注入——array (了解)


<property name="arr">    <array>        <value>123456</value>        <value>66666</value>    </array></property>
复制代码


(4)集合类型数据注入——set(了解)


 <property name="hs">     <set>         <value>itheima</value>         <value>66666</value>     </set></property>
复制代码


(5)集合类型数据注入——map(了解)


<property name="hm">    <map>        <entry key="name" value="itheima66666"/>        <entry key="value" value="6666666666"/>    </map></property>
复制代码


掌握:props、list

案例:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans        https://www.springframework.org/schema/beans/spring-beans.xsd">    <!--1.创建spring控制的资源-->    <!--bean可以使用多个名称,使用那么属性完成,中间使用,隔开-->    <!-- <bean id="userService" name="userService1" class="com.DI.service.Impl.UserServiceImpl">         &lt;!&ndash;3.将要租注入的引用类型的变量通过property属性进行注入,对应的name是要注入的变量名 使用ref属性声明要注入的bean的id&ndash;&gt;         <property name="userDao" ref="userDao"/>         <property name="num" value="666"/>         <property name="version" value="楠木"/>     </bean>-->    <!--将要注入的资源声明为bean,引用类型需要声明,非引用类型的不用声明,直接赋值-->    <!--<bean id="userDao" class="com.DI.Dao.Impl.UserDaoImpl">        &lt;!&ndash;不加name,也可以加index:从0开始&ndash;&gt;        <constructor-arg name="password" value="12345"/>        <constructor-arg name="username" value="root"/>        <constructor-arg name="driver" value="123"/>    </bean>
&lt;!&ndash;构造注入&ndash;&gt;
<bean id="userService" name="userService1" class="com.DI.service.Impl.UserServiceImpl"> &lt;!&ndash; 使用构造方法进行set注入,需要保障注入的属性与bean中定义的属性一致&ndash;&gt; &lt;!&ndash;一致指顺序一致或类型一致或使用index解决问题&ndash;&gt; <constructor-arg name="userDao" ref="userDao"/> <constructor-arg name="num" value="66666"/> <constructor-arg name="version" value="楠木"/> </bean>-->
<!--其余类型注入-->
<bean id="userDao" class="com.DI.Dao.Impl.UserDaoImpl"> <!--不加name,也可以加index:从0开始--> <constructor-arg name="password" value="12345"/> <constructor-arg name="username" value="root"/> <constructor-arg name="driver" value="123"/> </bean>
<bean id="userService" name="userService1" class="com.DI.service.Impl.UserServiceImpl"> <property name="userDao" ref="userDao"/> <property name="bookDao" ref="bookDao"/> </bean> <bean id="bookDao" name="bookDao" class="com.DI.Dao.Impl.BookDaoImpl"> <property name="al"> <list> <value>楠木1</value> <value>楠木2</value> </list> </property> <property name="props"> <props> <prop key="name">小米</prop> <prop key="value">大米</prop> </props> </property> <property name="arr"> <array> <value>6666</value> <value>9999</value> </array> </property> <property name="hs"> <set> <value>楠木3</value> <value>楠木4</value> </set> </property> <property name="hm"> <map> <entry key="name" value="楠木5"></entry> <entry key="name" value="楠木6"></entry> </map> </property> </bean>
</beans>
复制代码

6.3、拓展方式注入

  • 名称:p:propertyName,p:propertyName-ref

  • 类型:属性

  • 归属:bean 标签

  • 作用:为 bean 注入属性值

  • 格式:


  <bean p:propertyName="propertyValue" p:propertyName-ref="beanId"/>
复制代码


  • 注意:使用 p 命令空间需要先开启 spring 对 p 命令空间的的支持,在 beans 标签中添加对应空间支持


  <beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:p="http://www.springframework.org/schema/p"       xsi:schemaLocation="http://www.springframework.org/schema/beans     https://www.springframework.org/schema/beans/spring-beans.xsd">
复制代码


后续课程中还将开启其他的命名空间,方式同上


  • 案例:


   <bean         id="userService"         class="com.itheima.service.impl.UserServiceImpl"         p:userDao-ref="userDao"         p:bookDao-ref="bookDao"         />
复制代码

标签 P

简化书写,直接注入属性值


xmlns:p="http://www.springframework.org/schema/p"
复制代码


注意点:p 命名和 c 命名空间不能直接使用,需要导入 xml 约束!


xmlns:p="http://www.springframework.org/schema/p"xmlns:c="http://www.springframework.org/schema/c"
复制代码


<?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:p="http://www.springframework.org/schema/p"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.lfs.pojo.User" p:name="blue" p:age="18"/> </beans>
复制代码


加配置--测试:


test:


public class MyTest {    public static void main(String[] args) {        ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");        User user = context.getBean("user", User.class);        System.out.println(user);    }}
复制代码

标签 C

c 标签:通过构造器注入


 xmlns:c="http://www.springframework.org/schema/c"
复制代码


public class User {    private String name;    private int age;
public User() { }
public User(String name, int age) { this.name = name; this.age = age; }
复制代码


 <bean id="user" class="com.blue.pojo.User" p:name="blue" p:age="18"/>
<bean id="user" class="com.blue.pojo.User" c:age="18" c:name="blue"/>
复制代码

SpEL

  • Spring 提供了对 EL 表达式的支持,统一属性注入格式

  • 类型:属性值

  • 归属:value 属性值

  • 作用:为 bean 注入属性值

  • 格式:


  <property value="EL表达式"></bean>
复制代码


  • 注意:所有属性值不区分是否引用类型,统一使用 value 赋值

  • 所有格式统一使用 value=“********”

  • 常量 #{10} #{3.14} #{2e5} #{‘itcast’}

  • 引用 bean #{beanId}

  • 引用 bean 属性 #{beanId.propertyName}

  • 引用 bean 方法 beanId.methodName().method2()

  • 引用静态方法 T(java.lang.Math).PI

  • 运算符支持 #{3 lt 4 == 4 ge 3}

  • 正则表达式支持 #{user.name matches‘[a-z]{6,}’}

  • 集合支持 #{likes[3]}

  • 案例:


   <bean id="userService" class="com.itheima.service.impl.UserServiceImpl">       <property name="userDao" value="#{userDao}"/>       <property name="bookDao" value="#{bookDao}"/>       <property name="num" value="#{666666666}"/>       <property name="version" value="#{'itcast'}"/>  </bean>
复制代码

properties 文件加载

  • Spring 提供了读取外部 properties 文件的机制,使用读取到的数据为 bean 的属性赋值

  • 操作步骤

  • 1.准备外部 properties 文件

  • 2.开启 context 命名空间支持


  xmlns:context="http://www.springframework.org/schema/context"
复制代码


​ 3.加载指定的 properties 文件


<context:property-placeholder location="classpath:filename.properties">
复制代码


​ 4.使用加载的数据


<property name="propertyName" value="${propertiesName}"/>
复制代码


  • 注意:如果需要加载所有的 properties 文件,可以使用*.properties表示加载所有的 properties 文件

  • 注意:读取数据使用**${propertiesName}格式进行,其中 propertiesName**指 properties 文件中的属性名


<?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:p="http://www.springframework.org/schema/p"       xmlns:context="http://www.springframework.org/schema/context"       xsi:schemaLocation="http://www.springframework.org/schema/beans        https://www.springframework.org/schema/beans/spring-beans.xsd        http://www.springframework.org/schema/context        https://www.springframework.org/schema/context/spring-context.xsd
"> <!--1.加载context标签命名空间的支持--> <!--xmlns:context="http://www.springframework.org/schema/context" http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd -->
<!--2.加载配置文件-->
<context:property-placeholder location="classpath:*.properties"/>
<!--1.创建spring控制的资源--> <!--bean可以使用多个名称,使用那么属性完成,中间使用,隔开--> <bean id="bookDao" class="com.properties.dao.Impl.BookDaoImpl"/> <!--scope用于控制bean创建后的对象是否是单列--> <bean id="userDao" class="com.properties.dao.Impl.UserDaoImpl"> <property name="name" value="${username}"/> <property name="pass" value="${password}"/> </bean>
<bean id="userService" class="com.properties.service.Impl.UserServiceImpl"> <property name="userDao" ref="userDao"/> <property name="bookDao" ref="bookDao"/> </bean></beans>
复制代码

团队开发

  • 名称:import

  • 类型:标签

  • 归属:beans 标签

  • 作用:在当前配置文件中导入其他配置文件中的项

  • 格式:


  <beans>      <import />  </beans>
复制代码


  • 基本属性:


  <import resource=“config.xml"/>
复制代码


​ resource:加载的配置文件名


  • Spring 容器加载多个配置文件


  new ClassPathXmlApplicationContext("config1.xml","config2.xml");
复制代码


  • Spring 容器中的 bean 定义冲突问题

  • 同 id 的 bean,后定义的覆盖先定义的

  • 导入配置文件可以理解为将导入的配置文件复制粘贴到对应位置

  • 导入配置文件的顺序与位置不同可能会导致最终程序运行结果不同

ApplicationContext

  • 1.ApplicationContext 是一个接口,提供了访问 spring 容器的 API

  • 2.ClassPathXmlApplicationContext 是一个类,实现了上述功能

  • 3.ApplicationContext 的顶层接口是 BeanFactory

  • 4.BeanFactory 定义了 bean 相关的最基本操作

  • 5.ApplicationContext 在 BeanFactory 基础上追加了若干新功能


对比 BeanFactory


  • 1.BeanFactory 创建的 bean 采用延迟加载形式,使用才创建

  • 2.ApplicationContext 创建的 bean 默认采用立即加载形式


FileSystemXmlApplicationContext


  • 可以加载文件系统中任意位置的配置文件,而 ClassPathXmlApplicationContext 只能加载类路径下的配置文件


BeanFactory


Resource res = new ClassPathResource("applicationContext.xml");BeanFactory bf = new XmlBeanFactory(res);UserService userService = (UserService)bf.getBean("userService");
复制代码

第三方资源配置--->Druid

  • 阿里数据源方案 Druid


  <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">      <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>      <property name="url" value="jdbc:mysql://localhost:3306/spring_ioc"></property>      <property name="username" value="root"></property>      <property name="password" value="root"></property>  </bean>
复制代码


发布于: 刚刚阅读数: 3
用户头像

楠羽

关注

还未添加个人签名 2022.08.04 加入

还未添加个人简介

评论

发布
暂无评论
Spring之DI依赖注入_笔记_楠羽_InfoQ写作社区