关于java:SpringIOCDI自动装配

5次阅读

共计 7039 个字符,预计需要花费 18 分钟才能阅读完成。

什么是 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:不反对主动拆卸性能
正文完
 0