Spring--IOC、DI、自动装配

时迁
• 阅读 1799

什么是IOC

IOC全称是Inversion of Control(控制反转),所谓控制反转是对于程序本身而言,以前我们在创建对象的时候是自己通过new创建出来,而现在我们把这个权力交给了Spring去做,让它帮我们去创建对象和管理对象,对对象的控制权反转给了Spring

什么是DI

DI全称是Dependency Injection(依赖注入),所谓依赖注入是对于Spring的IOC容器而言,以前我们在给对象的属性赋值时有两种渠道,一种是通过带参数的构造方法,另一种是通过set方法。而现在IOC容器在创建对象的同时把属性的值注入进去。
什么是依赖:比如A对象的属性里有B对象,那么就叫A依赖B

Spring的DI实例

  • 依赖注入有两种方式,一种是基于对象的构造函数,另一种是基于对象属性对象的set方法,基本实现思路是这样的:

    • 基于构造函数:Spring参考bean配置,提取出bean对象的参数,通过构造方法实例化bean对象
    • 基于属性的set方
    • 法:Spring参考bean配置,首先先通过无参的构造方法实例化bean对象,然后通过set方法设置bean对象的属性
  • 注入基本数据类型(8大基本数据类+String)
/* User.java */
public class User {
     private String account;
     private String password;
     private Float balance;
     public User(String account, String password, Float balance) {
            this.account = account;
     this.password = password;
     this.balance = balance;
     }
        public User(){
            System.out.println("User对象创建了");
     }
        @Override
     public String toString() {
            return "User{" +
                    "account='" + account + ''' +
                    ", password='" + password + ''' +
                    ", balance=" + balance +
                    '}';
     }
        public String getAccount() {
            System.out.println("set方法调用了");
     return account;
     }
        public void setAccount(String account) {
            this.account = account;
     }
        public String getPassword() {
            return password;
     }
        public void setPassword(String password) {
            this.password = password;
     }
        public Float getBalance() {
            return balance;
     }
        public void setBalance(Float balance) {
            this.balance = balance;
     }
}
/* main函数 */
public class TestMain {
    public static void main(String[] args) {
         System.out.println(userDao.selectUserByAccount("2018"));
         AbstractApplicationContext factory = new ClassPathXmlApplicationContext("ApplicationContext.xml");
         User user = (User) factory.getBean("user");
         System.out.println(user);
     }
}
<!-- 配置文件-->
<?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 id="user" class="com.cjh.domain.User">
         <property name="account" value="2019"></property>
         <property name="password" value="123"></property>
         <property name="balance" value="777"></property>
     </bean>
</beans>

如果是基本数据类型/String的话,直接通过value写入要传递的值,底层会根据属性的具体类型将value转换成对应的数据类型

  • 注入聚合对象

    • 如果是对象里面套了另一个对象,有两种写法,一种是在bean里面配置一个bean,另一种是在bean里面引入一个外部bean
    • 第一种写法

      /* person.java */
      public class Person {
           private String name;
           //引入了上面的user对象
           private User user;
           public Person(){}
              @Override
           public String toString() {
                  return "Person{" +
                          "name='" + name + ''' +
                          ", user=" + user +
                          '}';
           }
              public String getName() {
                  return name;
           }
              public void setName(String name) {
                  this.name = name;
           }
              public User getUser() {
                  return user;
           }
              public void setUser(User user) {
                  this.user = user;
           }
      }
      //主函数
      public class TestMain {
           public static void main(String[] args) {  
                   System.out.println(userDao.selectUserByAccount("2018"));
                   ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
                   Person person = (Person) context.getBean("person");
                   System.out.println(person);
           }
      }
      <!-- 配置文件 -->
      <?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 id="person" class="com.cjh.domain.Person">
               <property name="name" value="john"></property>
               <property name="user">
                   <bean id="user" class="com.cjh.domain.User">
                       <property name="account" value="2019"></property>
                       <property name="password" value="123"></property>
                       <property name="balance" value="777"></property>
                   </bean>
               </property> 
           </bean>
      </beans>
      
    • 第二种写法

      • 通过property标签中的ref属性引入一个外部变量
<!-- 配置文件 -->
<?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 id="person" class="com.cjh.domain.Person">
         <property name="name" value="john"></property>
         <property name="user" ref="user"></property>
     </bean>
     <bean id="user" class="com.cjh.domain.User">
         <property name="account" value="2019"></property>
         <property name="password" value="123"></property>
         <property name="balance" value="777"></property>
     </bean>
</beans>
  • 注入集合

    • 注入List、set、map、properties集合
//TestCollection.java
package com.cjh.domain;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class TestCollection {
     private List<String> list;
     private Set<String> set;
     private Map<Integer, String> map;
     private Properties properties;
     public TestCollection(){}
        @Override
     public String toString() {
            return "TestCollection{" +
                    "list=" + list +
                    ", set=" + set +
                    ", map=" + map +
                    ", properties=" + properties +
                    '}';
     }
        public List<String> getList() {
            return list;
     }
        public void setList(List<String> list) {
            this.list = list;
     }
        public Set<String> getSet() {
            return set;
     }
        public void setSet(Set<String> set) {
            this.set = set;
     }
        public Map<Integer, String> getMap() {
            return map;
     }
        public void setMap(Map<Integer, String> map) {
            this.map = map;
     }
        public Properties getProperties() {
            return properties;
     }
        public void setProperties(Properties properties) {
            this.properties = properties;
     }
    }
//主函数
public class TestMain {
    public static void main(String[] args) {
      System.out.println(userDao.selectUserByAccount("2018"));
     ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
     TestCollection collection = (TestCollection) context.getBean("testCollection");
     System.out.println(collection);
     }
}
<!-- 配置信息 -->
<?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 id="testCollection" class="com.cjh.domain.TestCollection">
         <property name="list">
             <list value-type="java.lang.String">
                 <value>12</value>
                 <value>13</value>
                 <value>14</value>
                 <value>15</value>
             </list> 
         </property> 
         <property name="set">
             <set value-type="java.lang.String">
                 <value>abc</value>
                 <value>def</value>
                 <value>ghi</value>
                 <value>jkl</value>
                 <value>mno</value>
             </set> 
         </property> 
         <property name="map">
             <map key-type="java.lang.Integer" value-type="java.lang.String">
                 <entry key="1" value="a"/>
                 <entry key="2" value="b"/>
                 <entry key="3" value="c"/>
             </map> 
         </property> 
         <property name="properties">
             <props value-type="String">
                 <prop key="a">1</prop>
                 <prop key="b">2</prop>
                 <prop key="c">3</prop>
             </props>
         </property> 
     </bean>
</beans>
  • 注入null和空字符串
<bean id="person" class="com.cjh.domain.Person">
 <property name="name" value=""></property>
 <property name="user">
 <null></null> </property></bean>

如上的配置中,value什么都不给就默认为""空串,如果需要注入null,需要使用null标签,如果直接用value="null",Spring会把它解析成字符串null

自动装配

  • byName:在获取当前bean对象的时候,会根据当前对象的属性名,在配置文件下找到id/name属性与之一样的bean对象,装配给当前bean对象(通过属性的set方法)

    • 注意:这里我自己手动试过,当属性名与bean标签的name/id名不一致,但是set方法(set方法的命名规则:set+属性名)的属性名与name/id一致,也是可以装配成功的
    • 所以我得出:Spring是根据set方法的后缀属性名字与bean标签中的name/id匹配(个人意见)
  • byType:在获取当前bean对象的时候,根据当前对象属性的类型,在配置文件下找到相同类型的bean对象,并装配给当前bean对象(通过属性的set方法)

    • 如果beans下存在多个相同类型的bean对象,那么会报错
    • 如果当前bean对象的属性类型是接口、抽象类或者普通类的父类,有三种情况

      • 当属性对应的set方法的参数也是上述三种类型,如果beans下只有一个与之匹配的可实例化类型(子类/普通类的父类),那么装配成功
      • 当属性对应的set方法的参数也是上述三种类型,但是beans下有多个与之匹配的可实例化类型,那么报错
      • 当属性对应的set方法的参数是可实例化的类型,并且beans下只有一个与之匹配的类型,装配成功,如果有多个,那么报错
  • constructor:根据带参的构造方法进行装配

    • 根据构造方法的参数名和bean标签的id/name名是否一致
    • 根据构造方法的参数类型和bean标签的class类型是否一致

      • 如果构造方法的参数类型是父类,那么beans下要有唯一与之匹配的bean对象(出现多个不装配)
    • 以上两点满足其中1点即可装配
  • no:不支持自动装配功能
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
3年前
java面试题:Spring
Spring面试时,最好能结合底层代码说出IOC,AOP或SpringMVC的流程,能说出拦截器的底层。如果看过Spring的源码,并能结合设计模式表达,是很大的加分项。IOCQ:讲一下IOCIOC是"控制反转"。IOC将对象的控制权进行分离,交由第三方进行控制。IOC容器负责创建对象,管理对象.详情参见:https:/
Stella981 Stella981
3年前
Spring IoC、面向切面编程、事务管理等Spring基本概念详解
一、SpringIoC1.1重要概念1)控制反转(Inversionofcontrol)控制反转是一种通过描述(在java中通过xml或者注解)并通过第三方去产生或获取特定对象的方式。控制反转IoC(InversionofControl)是说创建对象的控制权进行转移,以前创建对象的主动权和
Wesley13 Wesley13
3年前
JAVA日常记录
11.IOC的优点是什么IOC(InversionofControl)控制反转,将控制权(创建对象和对象之间的依赖关系的权利)交给spring容器。接口驱动设计(InterfaceDrivenDesign)的好处,可以灵活提供不同的子类实现(其实就是解耦),提高程序的灵活性、可扩展性和可维护性。IOC模式将耦合代
Stella981 Stella981
3年前
Spring 学习笔记(二):SpringIoC
1IoC与DIIoC是InversionofControl的简称,也就是控制反转。通常来说,创建对象需要调用者手动创建,也就是newXXX()的方式。当Spring框架出现后,对象的实例不再由调用者创建,而是由Spring容器创建,这样控制权就由调用者转移到Spring容器,控制权发生了反
Easter79 Easter79
3年前
Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)
什么是IoC    IoC容器,最主要的就是完成对象的创建以及维护对象的依赖关系等。    所谓控制反转,包括两部分:一是控制,二是反转,就是把传统方式需要由代码来实现对象的创建、维护对象的依赖关系,反转给容器来帮忙管理和实现。所以我们必须要创建一个容器,同时需要一种描述来让容器创建对象与对象的关系。    Io
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
小万哥 小万哥
1年前
深入理解 Spring IoC 和 DI:掌握控制反转和依赖注入的精髓
概述在本文中,我们将介绍IoC(控制反转)和DI(依赖注入)的概念,以及如何在Spring框架中实现它们。什么是控制反转?控制反转是软件工程中的一个原则,它将对象或程序的某些部分的控制权转移给容器或框架。我们最常在面向对象编程的上下文中使用它。与传统编程相
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
美凌格栋栋酱 美凌格栋栋酱
4个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
时迁
时迁
Lv1
一去隔绝国,思归但长嗟。
文章
3
粉丝
0
获赞
0