IOC[inversion Of Control 反转控制](上)

简介: IOC[inversion Of Control 反转控制](上)

IOC[inversion Of Control 反转控制]


在传统的开发模式下,需要使用JdbcUtils / 反射,由程序员编写程序, 在程序中读取配置信息 ,然后创建对象, new Object???() // 反射方式,再使用对象完成任务。程序员不能够专注的实现对象对业务的处理。


IOC的开发模式很好的解决了这个问题。Spring 根据配置文件 xml/注解 创建对象,并将对象放入到容器(ConcurrentHashMap)中, 可以完成对象之间的依赖。


当需要使用某个对象实例的时候, 可以直接从容器中获取。程序员就可以更加关注如何使用对象完成相应的业务, (以前需要 new … ==> 注解/配置 方式)。


DI(Dependency Injection)依赖注入,可以理解成是 IOC 的另外叫法。Spring 最大的价值是通过配置,给程序提供需要使用的web 层[Servlet(Action/Controller)]/Service/Dao/[JavaBean/entity]对象, 这个是核心价值所在,也是 ioc 的具体体现,实现解耦。


Spring 快速入门实例


在开始之前我们需要下载spring5的开发包。


commons-logging-1.1.3.jar:spring日志需要的jar。


spring开发ioc基本包:


spring-beans-5.3.8.jar

spring-context-5.3.8.jar

spring-core-5.3.8.jar

spring-expression-5.3.8.jar


还要导入Dom4j.jar包


创建一个beans.xml存放bean。

<!--配置Monster对象-->
    <bean id="monster" class="com.spring.bean.Monster">
        <property name="monsterId" value="1"/>
        <property name="name" value="蜈蚣精"/>
        <property name="skill" value="蜇人"/>
    </bean>


获取对象并给对象属性赋值输出。

package com.spring.test;
import com.spring.beans.Monster;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
public class ApplicationContext {
    private ConcurrentHashMap<String, Object> ioc =
    new ConcurrentHashMap<>();
    public ApplicationContext(String iocBeanXmlFile) throws DocumentException,
    ClassNotFoundException, IllegalAccessException, InstantiationException {
        //反射的方式得到->使用dom4j
        //得到一个解析器
        SAXReader reader = new SAXReader();
        Document document = reader.read(new File(iocBeanXmlFile));
        //1. 得到rootElement
        Element rootElement = document.getRootElement();
        //2. 获取第1 个bean, 如果有多个就遍历所有
        Element bean = (Element) rootElement.elements("bean").get(0);
        String id = bean.attributeValue("id");
        String classFullPath = bean.attributeValue("class");
        List<Element> property = bean.elements("property");
        Integer monsterId = Integer.parseInt(property.get(0).attributeValue("value"));
        String name = property.get(1).attributeValue("value");
        String skill = property.get(2).attributeValue("value");
        //3. 使用反射创建bean 实例,并放入到ioc 中
        Class cls = Class.forName(classFullPath);
            Monster instance = (Monster)cls.newInstance();
        instance.setMonsterId(monsterId);
        instance.setName(name);
        instance.setSkill(skill);
        ioc.put(id, instance);
        }
        public Object getBean(String id) {
        return ioc.get(id);
    }
}


创建一个测试类

package com.spring.test;
import com.spring.beans.Monster;
import org.dom4j.DocumentException;
public class SpringIOCTest {
    public static void main(String[] args) throws DocumentException,
    IllegalAccessException, InstantiationException, ClassNotFoundException {
        //得到beans.xml 文件.
        ApplicationContext ioc = new ApplicationContext("src/beans.xml");
        Monster monster01 = (Monster)ioc.getBean("monster01");
        System.out.println("ioc 的monster01= " + monster01);
    }
}


获取bean的方法


通过类型获取bean


//通过类型来获取容器的bean 对象
@Test
public void getMonsterByType() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
    //创建容器
Monster monster = ioc.getBean(Monster.class);
    //获取容器中Monster类型的bean对象
System.out.println("monster=" + monster);
    Monster monster1 = ioc.getBean(Monster.class);
System.out.println("monster == monster1 的值= " + (monster == monster1));
}

按类型来获取bean, 要求ioc 容器中的同一个类的bean 只能有一个, 否则会抛出异常NoUniqueBeanDefinitionException。一般应用于在一个线程中只需要一个对象实例(单例)的情况。在容器配置文件(比如beans.xml)中给属性赋值, 底层是通过setter 方法完成的。


通过构造器配置bean


在spring的ioc容器,可以通过构造器来配置bean对象。

<bean id="monster02" class="com.spring.beans.Monster">
<constructor-arg value="2" index="0"/>
<constructor-arg value="蜘蛛精" index="1"/>
<constructor-arg value="蛛丝束缚" index="2"/>
     //1. 通过index 属性来区分是第几个参数
</bean>
<!--数据类型就是对应的Java 数据类型,按构造器参数顺序-->
<bean id="monster03" class="com.spring.beans.Monster">
<constructor-arg value="3" type="java.lang.Integer"/>
<constructor-arg value="白骨精" type="java.lang.String"/>
<constructor-arg value="白骨鞭" type="java.lang.String"/>
</bean>
//2. 通过type 属性来区分是什么类型(按照顺序)


通过p名称空间配置bean


<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">
<!--在spring 的ioc 容器, 可以通过p 名称空间来配置bean 对象-->
<bean id="monster04" class="com.spring.beans.Monster"
p:monsterId="4"
p:name="红孩儿"
p:skill="吐火~"
/>


引用/注入其它bean 对象


在spring 的ioc 容器, 可以通过ref 来实现bean 对象的相互引用。

<!-- bean 对象的相互引用
        1. 其它含义和前面一样
        2. ref 表示memberDAO 这个属性将引用/指向id = memberDAOImpl 对象
-->
<bean id="memberServiceImpl" class="com.spring.service.MemberServiceImpl">
<property name="memberDAO" ref="memberDAOImpl"/>
</bean>
<bean id="memberDAOImpl" class="com.spring.dao.MemberDAOImpl"/>


引用/注入内部bean 对象


<bean id="memberServiceImpl02"
class="com.spring.service.MemberServiceImpl">
    <property name="memberDAO">
      <bean class="com.spring.dao.MemberDAOImpl"/>
    </property>
</bean>


引用/注入集合/数组类型


<bean id="master01" class="com.spring.beans.Master">
    <property name="name" value="太上老君"/>
    <!-- 给bean 对象的list 集合赋值-->
    <property name="monsterList">
        <list>
            <ref bean="monster03"/>
            <ref bean="monster02"/>
        </list>
    </property>
    <!-- 给bean 对象的map 集合赋值-->
    <property name="monsterMap">
        <map>
            <entry>
            <key>
              <value>monsterKey01</value>
            </key>
            <ref bean="monster01"/>
            </entry>
            <entry>
                <key>
              <value>monsterKey02</value>
                </key>
               <ref bean="monster02"/>
            </entry>
        </map>
    </property>
    <!-- 给bean 对象的properties 集合赋值-->
    <property name="pros">
        <props>
            <prop key="k1">Java 工程师</prop>
            <prop key="k2">前端工程师</prop>
            <prop key="k3">大数据工程师</prop>
        </props>
    </property>
    <!-- 给bean 对象的数组属性注入值-->
    <property name="monsterName">
        <array>
            <value>银角大王</value>
            <value>金角大王</value>
        </array>
    </property>
        <!-- 给bean 对象的set 属性注入值-->
    <property name="monsterSet">
        <set>
            <ref bean="monster01"/>
            <bean class="com.spring.beans.Monster">
                <property name="monsterId" value="10"/>
                <property name="name" value="玉兔"/>
                <property name="skill" value="钻地洞"/>
            </bean>
        </set>
    </property>
</bean>


测试

@Test
public void setCollectionByPro() {
    ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
        Master master01 = ioc.getBean("master01", Master.class);
    //获取list 集合
    System.out.println("======list=======");
    List<Monster> monster_list = master01.getMonsterList();
    for (Monster monster : monster_list) {
      System.out.println(monster);
    }
    //获取map 集合
    System.out.println("======map=======");
    Map<String, Monster> monster_map = master01.getMonsterMap();
    Set<Map.Entry<String, Monster>> entrySet = monster_map.entrySet();
    for (Map.Entry<String, Monster> entry : entrySet) {
       System.out.println(entry);
    }
    //获取properties 集合
    System.out.println("======properties=======");
    Properties pros = master01.getPros();
    String property1 = pros.getProperty("k1");
    String property2 = pros.getProperty("k2");
    String property3 = pros.getProperty("k3");
    System.out.println(property1 + "\t" + property2 + "\t" + property3);
    //获取数组
    System.out.println("======数组=======");
    String[] monsterName = master01.getMonsterName();
    for (String s : monsterName) {
      System.out.println("妖怪名= " + s);
    }
    //获取set
    System.out.println("======set=======");
    Set<Monster> monsterSet = master01.getMonsterSet();
    for (Monster monster : monsterSet) {
      System.out.println(monster);
    }
}


细节

  1. 1.主要掌握List/Map/Properties 三种集合的使用。
  2. 2.Properties 集合的特点。
  1. 1.这个Properties 是Hashtable 的子类, 是key-value 的形式。
  2. 2.key 是string 而value 也是string。


通过util 名称空间创建list


<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:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/util
    http://www.springframework.org/schema/util/spring-util.xsd">
    <!--通过util 名称空间来创建list 集合,可以当做创建bean 对象的工具来使用-->
    <util:list id="myListBook">
            <value>三国演义</value>
            <value>西游记</value>
            <value>红楼梦</value>
            <value>水浒传</value>
    </util:list>
    <bean id="bookStore" class="com.spring.beans.BookStore">
      <property name="bookList" ref="myListBook"/>
    </bean>


级联属性赋值


spring 的ioc 容器, 可以直接给对象属性的属性赋值, 即级联属性赋值。

<bean id="emp" class="com.spring.beans.Emp">
        <property name="name" value="jack"/>
        <property name="dept" ref="dept"/>
        <property name="dept.name" value="Java 开发部"/> 
</bean>
<bean id="dept" class="com.spring.beans.Dept"/>


package com.spring.beans;
public class Dept {
        private String name;
        public Dept() {
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
}


package com.spring.beans;
public class Emp {
    private String name;
    private Dept dept;
    public Emp() {
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
      this.name = name;
    }
    public Dept getDept() {
       return dept;
    }
    public void setDept(Dept dept) {
      this.dept = dept;
    }
}


相关文章
|
4月前
|
前端开发 Java 程序员
图书管理系统调整——修改注解(引入IoC、DI思想)
图书管理系统调整——修改注解(引入IoC、DI思想)
27 2
|
安全 Java 程序员
IOC[inversion Of Control 反转控制](下)
IOC[inversion Of Control 反转控制](下)
48 0
|
XML Java 数据格式
一文讲透Spring的IOC反转控制
一文讲透Spring的IOC反转控制
81 0
|
XML 设计模式 安全
Spring的反转控制你真的明白了吗?(上)
Spring的反转控制你真的明白了吗?
|
SQL 设计模式 开发框架
Spring的反转控制你真的明白了吗?(下)
Spring的反转控制你真的明白了吗?
|
Java 测试技术 容器
一篇文章解释清楚IOC和DI
一篇文章解释清楚IOC和DI
|
开发框架 Java Spring
什么是 Inversion of Control 控制反转
什么是 Inversion of Control 控制反转
75 0