Spring IoC

Posted hetaoyuan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring IoC相关的知识,希望对你有一定的参考价值。

Web Explain:

技术图片

 

 

 

什么是Spring IoC?控制翻转,依赖注入

为什么用到Spring IoC

之前在写代码的时候,如果要在一个类里面,获取另一个类里面的属性方法,首先需要在本类里面调用另一个类的构造方法,通过构造方法获取其对象在调用其类里面的公共方法并通过get、set获取并修改其属性值;

或者,通过类的继承、实现接口来取得类与类之间的联系

但在Spring中,我们摒弃上面的方法,通过SpringIoC来解耦类与类之间的关系,不用再new,这个容器就叫applicationContext.xml,它就是Spring容器,也是Spring框架

那么创建这个容器的方式都有哪些?

SpringIoc的创建方式常用的为xml配置(需要额外注意构造中参数列表的参数顺序)和注解方式(推荐,在SpringBoot中也常用)

现在我们在idea上试着写一个简单的SpringIoC,来调用另一个类的属性和方法

 

第一步,在pom.xml中添加Spring的依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.ming</groupId>
    <artifactId>ArvinSpringProjects</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!--
        spring core
        spring beans
        spring context
        spring aop

    -->

    <dependencies>
        <!--spring core jar-->
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
        <!--
            relevant form between class and others
        -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <!--
            Spring Context
        -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
        <!--Aspect Oriented Programming-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>RELEASE</version>
            <scope>test</scope>
        </dependency>

        <!--
            Junit
        -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>
</project>

第二步,再加载核心配置文件,Application.context,它就是Spring容器,现在把new的工作交给容器去做,been通过id来表示,class为你想要实例化的类,如果id的名字为“person”,这句话就相当于

Person person = new Person(),即容器帮助你new了一个person,class为该类包下的路径,<property name="pName" value="arvin"/>只要是property就是setter的注入,value代表修改的值,name为构造传参,pName为普通类属性

 

Application来自Spring包

<?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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">


    <!--
        Person person = new Person();
    -->
    <bean id="person" class="com.hhy.bean.Person">
       <!-- <property name="pName" value="arvin"/>-->
        <constructor-arg name="age" value="20"/>
        <constructor-arg name="name"  type="java.lang.String"  value="michael jackson"/>
    </bean>


</beans>

 

写一个普通的Person类

package com.hhy.bean;


/**
 * Person p = new Person
 * p.setpName("arvin");
 *
 *
 * p.getpName();
 */

public class Person 

    //DI
    private String pName;

    private int pAge;


    public Person()

    

    public Person(String name, int age)
        this.pName = name;
        this.pAge = age;
    

    public String getpName() 
        return pName;
    

    public void setpName(String pName) 
        this.pName = pName;
    

    public int getpAge() 
        return pAge;
    

    public void setpAge(int pAge) 
        this.pAge = pAge;
    

    /**
     * sayHello is defined by arvin
     * @return
     */
    public void sayHello()
        System.out.println("hello nice to meeting you");
    

    @Override
    public String toString() 
        return "Person" +
                "pName=‘" + pName + ‘\\‘‘ +
                ‘‘;
    

 

 

通过容器实例化它之后,第三步获取bean对象,context.getbean就获取到了bean类对象,由于Spring容器在接受时也不知道它是什么类型,所以需要强转为bean类型,第四步,测试application

package com.hhy;


import com.hhy.bean.Person;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringTest 

    private Person person = null;

    @Before
    public void testInitial()
        //acquire object from spring container
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        person = (Person) context.getBean("person");
    

    @Test
    public void testMethod()
        //Person person = new Person();
        person.sayHello();
        System.out.println("pName = " + person.getpName() + ", pAge = " + person.getpAge());
    

测试打印结果:

hello nice to meeting you
pName = michael jackson, pAge = 20

  

 

 

 

每个需要容器调用的类中必须要有set方法。通过set控制属性,普通类通过set注入bean的对象的value值

 

刚才说过IoC伴随DI(依赖注入),有Setter、构造、接口注入的方法,注入的是什么?属性,也就是成员变量,并且普通类都要带有无参构造

 

关于注入的类型不止有String类型,还有map、set、list、数组、int、String数组

 

再创建一个bean类,来一个个测试我们的注入类型,既然用setter注入,就一定要选择我们的默认构造方法和set方法再加一个tostring方便打印

package com.hhy.bean2;

import java.util.*;

/**
 * test injection from spring framework
 * setter(recommend)
 */
public class Bean1 

    private String strValue;

    private int intValue;

    private Map mapValue;

    private Set setValue;

    private List listValue;

    private String [] arrayValue;

    //Date java.util.Date;
    private Date dateValue;


    public Bean1()

    

    //DI
    public Date getDateValue() 
        return dateValue;
    

    public void setDateValue(Date dateValue) 
        this.dateValue = dateValue;
    

    public String getStrValue() 
        return strValue;
    

    public void setStrValue(String strValue) 
        this.strValue = strValue;
    

    public int getIntValue() 
        return intValue;
    

    public void setIntValue(int intValue) 
        this.intValue = intValue;
    

    public Map getMapValue() 
        return mapValue;
    

    public void setMapValue(Map mapValue) 
        this.mapValue = mapValue;
    

    public Set getSetValue() 
        return setValue;
    

    public void setSetValue(Set setValue) 
        this.setValue = setValue;
    

    public List getListValue() 
        return listValue;
    

    public void setListValue(List listValue) 
        this.listValue = listValue;
    

    public String[] getArrayValue() 
        return arrayValue;
    

    public void setArrayValue(String[] arrayValue) 
        this.arrayValue = arrayValue;
    


    @Override
    public String toString() 
        return "Bean1" +
                "strValue=‘" + strValue + ‘\\‘‘ +
                ", intValue=" + intValue +
                ", mapValue=" + mapValue +
                ", setValue=" + setValue +
                ", listValue=" + listValue +
                ", arrayValue=" + Arrays.toString(arrayValue) +
                ‘‘;
    

 

我们再来建一个applicationcontext用来测试属性注入

<?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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">


    <!--test properties injection-->
    <bean id="bean1" class="com.hhy.bean2.Bean1">
        <!--string-->
        <property name="strValue" value="xiaoming"/>
        <!--int-->
        <property name="intValue">
            <value>100</value>
        </property>
        <!--map-->
        <property name="mapValue">
            <map>
                <entry key="key1" value="value1"/>
                <entry key="key2" value="value2"/>
                <entry key="key3" value="value3"/>
            </map>
        </property>

        <!--list-->
        <property name="listValue">
            <list>
                <value>list1</value>
                <value>list2</value>
                <value>list3</value>
            </list>
        </property>


        <!--set-->
        <property name="setValue">
            <set>
                <value>setValue1</value>
                <value>setValue2</value>
                <value>setValue3</value>
            </set>
        </property>

        <property name="arrayValue">
            <list>
                <value>arrayValue1</value>
                <value>arrayValue2</value>
                <value>arrayValue3</value>
            </list>
        </property>


        <property name="dateValue" value="2019-07-23"/>
    </bean>


    <!--
        DateEditProperties dep = new DateEditProperties();
    -->
    <bean id="edit" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
        <property name="customEditors">
            <map>
                <entry key="java.util.Date" value="com.hhy.bean2.DateEditProperties"/>
            </map>
        </property>
    </bean>

    <bean id="userinfo" class="com.hhy.bean.UserInfo">
        <property name="username" value="lisi"/>
        <!--references-->
        <property name="person" ref="myPersonId"/>
    </bean>


    <bean id="myPersonId" class="com.hhy.bean.Person">
        <property name="pName" value="zhansan"/>
        <property name="pAge">
            <value>10</value>
        </property>
    </bean>
</beans>

 

只要是property就是setter注入,value代表你set的值

需要注意的是:在容器中,key和value不管是什么数据类型都是字符串,只不过到具体类中对应的才是本来的类型

 

配置完容器后,再去测试类里面写测试

package com.hhy;


import com.hhy.bean.Person;
import com.hhy.bean2.Bean1;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringTest2 

    private Bean1 bean1 = null;

    @Before
    public void testInitial()

        ApplicationContext context = new ClassPathXmlApplicationContext(new String[]"applicationContext-beans.xml");
        bean1 = (Bean1) context.getBean("bean1");
    

    @Test
    public void testMethod()
        System.out.println("bean1 strValue = " + bean1.getStrValue());
        System.out.println("bean1 listValue = " + bean1.getListValue());
        System.out.println("bean1 setValue = " + bean1.getSetValue());
        System.out.println("bean1 intValue = " + bean1.getIntValue());
        System.out.println("bean1 mapValue = " + bean1.getMapValue());
        System.out.println("bean1 arrayValue = " + bean1.getArrayValue());

        //date
        System.out.println("bean1 dateValue = " + bean1.getDateValue());
    

打印结果:

text = 2019-07-23
bean1 strValue = xiaoming
bean1 listValue = [list1, list2, list3]
bean1 setValue = [setValue1, setValue2, setValue3]
bean1 intValue = 100
bean1 mapValue = key1=value1, key2=value2, key3=value3
bean1 arrayValue = [Ljava.lang.String;@43a0cee9
bean1 dateValue = Tue Jul 23 00:00:00 CST 2019

  

值得一提的是,上面的日期类,需要重新写一个类定义一下格式,因为日期分为很多时区,而且格式也不同,这里用到

SimpleDateFormat sdf = new SimpleDateFormat("yyyy--MM-dd");
package com.hhy.bean2;

import org.springframework.beans.propertyeditors.PropertiesEditor;

import java.beans.PropertyEditorSupport;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateEditProperties extends PropertyEditorSupport 


    private String formatting = "yyyy-MM-dd";


    @Override
    public void setAsText(String text) throws IllegalArgumentException 
        System.out.println("text = " + text);
        SimpleDateFormat sdf = new SimpleDateFormat(formatting);
        try
            Date date = sdf.parse(text);
            this.setValue(date);
        catch(Exception ex)
            ex.printStackTrace();
        

    

 

以上是关于Spring IoC的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot脚手架项目002-004.Spring IOC_权限管理系统_Spring:什么是IOCSpring Bean注入SpringBean的注解bean的加载流程

Springday02 jabcTemplate注解IOC创建对象注解IOC注入注解 IO生命周期纯注解IOCSpring-junitAOP-JDK和CGLIB动态代理

Spring快速入门

Spring框架--Spring JDBC

Spring框架--AOP面向切面编程

Spring框架--AOP面向切面编程