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();
        }

    }
}

 

posted @ 2019-08-24 17:19  何浩源  阅读(203)  评论(0编辑  收藏  举报
//一下两个链接最好自己保存下来,再上传到自己的博客园的“文件”选项中