Study(2) SpringIOC 基于xml方式依赖注入

1.原始关系(非IOC)

对象之间依赖关系由对象自己来建立
A—->B
A
B b = new B();
b.f1();
B
f1();
C
f1();

2.IOC

(1).Ioc (Inversion of controll 控制反转):对象之间的依赖关系由容器建立

(2).DI (Dependency Injection 依赖注入):容器通过调用对象提供的set方法或者构造器来建立依赖关系

注:IOC是目标,DI是手段

3.bean注入(set方式,构造器方式)

方式一:set方法依赖注入(A—->B)

property元素:表示使用set方法来注入依赖关系,其中name属性指定属性名
            ref 属性指定属性值(是被注入的bean的id)

(不推荐,若想 A—-C 代码改动很大)

(1).建立 A,B对象

public class B {
    public B(){
        System.out.println("B()");
    }
    public void f1(){
        System.out.println("B-f1()");
    }
}

public class A {
    private B b;
    public void setB(B b){
        System.out.println("setB()");
        this.b = b;
    }
    public A(){
        System.out.println("A()");
    }
    public void exeute(){
        System.out.println("exeute()");
        b.f1();
    }
}

(2).ioc.xml

<bean id="b1" class="cn.com.sinodata.Ioc.B"></bean>
    <!--
        property元素:表示使用set方法来注入依赖关系,其中name属性指定属性名
        ref属性指定属性值(是被注入的bean的id)
    -->
<bean id="a1" class="cn.com.sinodata.Ioc.A">
    <property name="b" ref="b1"></property>
</bean>

(3).测试

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("IOC.xml");
       A a1 = applicationContext.getBean("a1", A.class);
       a1.exeute();

(4).spring容器运行流程说明

spring容器启动后,会读配置文件(ioc.xml),创建所有单例(scope=”singleton”)对象,检测到 A 对象 中property元素时,容器会使用set方法注入 B 对象

方式一:set方法依赖注入(A <—-C)

property元素:表示使用set方法来注入依赖关系,其中name属性指定属性名
            ref 属性指定属性值(是被注入的bean的id)

(推荐此方法,若想 A <—-B 或者 A<—-C ,代码只需改动配置文件即可)

若想代码变化少,建立接口,让 B 和 C 都实现这个接口

代码优化:

(1).建立 A,B,C对象

public interface BC {
    public void f1();
}

public class B implements BC{
    public B(){
        System.out.println("B()");
    }
    public void f1(){
        System.out.println("B-f1()");
    }
}

public class C implements BC{
    public C(){
        System.out.println("C()");
    }
    public void f1(){
        System.out.println("C-f1()");
    }
}

public class A {
    private BC bc;
    public void setBc(BC bc){
        System.out.println("setBC()");
        this.bc = bc;
    }
    public A(){
        System.out.println("A()");
    }
    public void exeute(){
        System.out.println("exeute()");
        bc.f1();
    }
}

(2).ioc.xml

 <bean id="b1" class="cn.com.sinodata.Ioc.B"></bean>
        <!--
            property元素:表示使用set方法来注入依赖关系,其中name属性指定属性名
            ref属性指定属性值(是被注入的bean的id)
        -->
<bean id="c1" class="cn.com.sinodata.Ioc.C"></bean>

若 A <-----B 使用
    <bean id="a1" class="cn.com.sinodata.Ioc.A">
        <property name="bc" ref="b1"></property>
    </bean>

若 A <-----C 使用
    <bean id="a1" class="cn.com.sinodata.Ioc.A">
        <property name="bc" ref="c1"></property>
    </bean>

方式二:构造器方式注入

constructor-arg元素:用来配置构造器方式的注入,
                ref: 指定构造器注入的bean的Id
                index: 指定参数下标(从0开始)

(1).建立 A,B,C对象

public interface BC {
    public void f1();

}

public class B implements BC{

    public B(){
        System.out.println("B()");
    }

    public void f1(){
        System.out.println("B-f1()");
    }
}

public class C implements BC{
    public C(){
        System.out.println("C()");
    }

    public void f1(){
        System.out.println("C-f1()");
    }

}

public class A {

    private BC bc;

    public A(BC bc){
        this.bc = bc;
    }

    public A(){
        System.out.println("A()");
    }

    public void excute(){
        System.out.println("A-excute()");
        bc.f1();
    }
}

(2).ioc.xml

<bean id="b2" class="cn.com.sinodata.IocCons.B"></bean>
   <bean id="c2" class="cn.com.sinodata.IocCons.C"></bean>

   <!--
       constructor-arg元素:用来配置构造器方式的注入,
                       ref: 指定构造器注入的bean的Id
                       index: 指定参数下标(从0开始)
   -->
   <bean id="a2" class="cn.com.sinodata.IocCons.A">
       <constructor-arg index="0" ref="c2"></constructor-arg>
   </bean>

(3).测试

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("IocCon.xml");
       cn.com.sinodata.IocCons.A a2 = applicationContext.getBean("a2", cn.com.sinodata.IocCons.A.class);
       a2.excute();

4.自动装配

自动装配:spring容器根据某种规则,自动建立对象之间的依赖关系

注意:

(1).默认情况下,容器不会自动装配的

(2).可以通过指定autowire属性,告诉容器进行自动装配(容器仍然需要通过调用set方法或者构造器来完成依赖关系的建立)

autowire属性:表示让容器自动装配,该属性有三个值
        byName:(优先使用)
            容器依据属性名查找对应的bean,调用对应的set方法完成注入。
                注:
                    a: 如果找不到对应的bean.注入null
                    b: 不可能找到多个符合条件的bean,根据(id)
        byType: 
            容器依据属性类型查找对应的bean,然后调用对应的set方法来完成注入
                注:
                    a: 如果找不到对应的bean.注入null
                    b:  有可能找到多个符合条件的bean,此时会报错 ,根据(class类型)
        constructor: 
            容器依据属性名查找对应的bean,调用对应的构造器完成注入。

(1).建立Waiter,Restarant类

public class Waiter {
public Waiter(){
        System.out.println("Waiter()");
    }
}

public class Restarant {

    private Waiter waiter;
    public void setWaiter(Waiter waiter) {
        System.out.println("setWaiter");
        this.waiter = waiter;
    }
    public Restarant(){
        System.out.println("Restarant()");
    }
    @Override
    public String toString() {
        return "[Waiter="+this.waiter+"]";
    }
}

(2).IocCon.xml

<!--
        autowire属性:表示让容器自动装配,该属性有三个值
                byName:容器依据属性名查找对应的bean,调用对应的set方法完成注入。
                        注:
                            a: 如果找不到对应的bean.注入null
                            b: 不可能找到多个符合条件的bean,根据(id)
                byType: 容器依据属性类型查找对应的bean,然后调用对应的set方法来完成注入
                        注:
                            a: 如果找不到对应的bean.注入null
                            b:  有可能找到多个符合条件的bean,此时会报错 ,根据(class类型)
                constructor: 容器依据属性名查找对应的bean,调用对应的构造器完成注入。
    -->
    <bean id="waiter" class="cn.com.sinodata.IocCons.Waiter"></bean>
    <bean id="restarant"  class="cn.com.sinodata.IocCons.Restarant" autowire="byName"></bean>
    <bean id="restarant"  class="cn.com.sinodata.IocCons.Restarant" autowire="byType"></bean>
    <bean id="restarant"  class="cn.com.sinodata.IocCons.Restarant" autowire="constructor"></bean>

(3).测试

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("IocCon.xml");
Restarant restarant = applicationContext.getBean("restarant", Restarant.class);
System.out.println(restarant.toString());

5.Spring 注入值

(1).新建ValueBean

public class ValueBean {
    private String name;
    private int age;

    private List<String> city;
    private Set<String> interest;
    private Map<String,Double> score;
    private Properties properties;

    public ValueBean(){
        System.out.println("ValueBean()");
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    public void setScore(Map<String, Double> score) {
        this.score = score;
    }

    public void setInterest(Set<String> interest) {
        this.interest = interest;
    }

    public void setCity(List<String> city) {
        this.city = city;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "ValueBean{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", city=" + city +
                ", interest=" + interest +
                ", score=" + score +
                ", properties=" + properties +
                '}';
    }
}

(2).value.xml

注入基本类型的值
<bean id="valueBean" class="cn.com.sinodata.Value.ValueBean">
    <property name="name" value="zhangsan"></property>
    <property name="age" value="12"></property>
</bean>
注入集合类型的值(List Set Map Properties)
<bean id="valueBean" class="cn.com.sinodata.Value.ValueBean">

    <property name="city" >
        <list>
            <value>北京</value>
            <value>深圳</value>
            <value>上海</value>
        </list>
    </property>
    <property name="interest">
        <set>
            <value>唱歌</value>
            <value>跳舞</value>
            <value>唱歌</value>
        </set>
    </property>
    <property name="score">
        <map>
            <entry key="数学" value="23.0"></entry>
            <entry key="语文" value="33.2"></entry>
        </map>
    </property>
    <property name="properties">
        <props>
            <prop key="username">root</prop>
            <prop key="password">123456</prop>
        </props>
    </property>
</bean>

引用的方式注入集合类型的值

加入
    xmlns:util="http://www.springframework.org/schema/util"
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"

 <!--将集合类型的值配置成一个bean-->
    <util:list id="cityBean">
        <value>北京</value>
        <value>深圳</value>
        <value>上海</value>
    </util:list>
    <util:set id="interestBean">
        <value>唱歌</value>
        <value>跳舞</value>
        <value>唱歌</value>
    </util:set>
    <util:map id="scoreBean">
        <entry key="数学" value="23.0"></entry>
        <entry key="语文" value="33.2"></entry>
    </util:map>
    <util:properties id="propertiesBean">
            <prop key="username">root</prop>
            <prop key="password">123456</prop>
    </util:properties>

    <!--引用的方式注入集合类型的值-->
    <bean id="valueBean2" class="cn.com.sinodata.Value.ValueBean">
        <property name="city" ref="cityBean"/>
        <property name="properties" ref="propertiesBean"/>
        <property name="score" ref="scoreBean"/>
        <property name="interest" ref="interestBean"/>
    </bean>

(3).测试

 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("value.xml");
    ValueBean valueBean = applicationContext.getBean("valueBean", ValueBean.class);
    System.out.println(valueBean.toString());

// 引用的方式注入集合类型的值
ValueBean valueBean = applicationContext.getBean("valueBean2", ValueBean.class);
System.out.println(valueBean.toString());

6.读取properties文件的内容

(1).新建config.properties文件

pagesize=10

(2).value.xml

读取properties文件内容,
        classpath: 按照类路径来搜索
        spring容器会根据路径找到对应的properties文件,然后读取该文件的内容到Properties对象       
<util:properties id="config" location="classpath:config.properties"/>

(3).测试

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("value.xml");
System.out.println(applicationContext.getBean("config"));

7.使用spring表达式

可以使用spring表达式读取其他bean的属性,语法类似于el表达式

valueBean.name
valueBean.city[0]  valueBean为ValueBean的id,city为ValueBean的属性,[0]为list类型city属性的下标

(1).新建ValueBean和SeplBean

public class ValueBean {
    private String name;
    private List<String> city;
    private Map<String,Double> score;
    public ValueBean(){
        System.out.println("ValueBean()");
    }
    public String getName() {
        return name;
    }
    public List<String> getCity() {
        return city;
    }
    public Map<String, Double> getScore() {
        return score;
    }
    public void setScore(Map<String, Double> score) {
        this.score = score;
    }
    public void setCity(List<String> city) {
        this.city = city;
    }
    public void setName(String name) {
        this.name = name;
    }
}

public class SeplBean {
    private String name;
    private String city;
    private Double score;
    private String pageSize;
    public SeplBean(){
        System.out.println("seplbean()");
    }
    public void setScore(Double score) {
        this.score = score;
    }
    public void setCity(String city) {
        this.city = city;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setPageSize(String pageSize) {
        this.pageSize = pageSize;
    }
    @Override
    public String toString() {
        return "SeplBean{" +
                "name='" + name + '\'' +
                ", city='" + city + '\'' +
                ", score=" + score +
                ", pageSize='" + pageSize + '\'' +
                '}';
    }
}

新建 seplutrl.properties 文件 ,pagesize=10

(2).sepl.xml

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


//此类中必须包含get set方法,否则,使用spring表达式访问不到属性值
        <bean id="valueBean" class="cn.com.sinodata.Value.ValueBean">
            <property name="name" value="eee"/>
            <property name="score">
                <map>
                    <entry key="math" value="233"></entry>
                </map>
            </property>
            <property name="city" ref="cityutil"/>
        </bean>

        <util:list id="cityutil">
            <value>中国北京</value>
            <value>中国深圳</value>
        </util:list>

        <util:properties id="seplutil" location="classpath:seplutrl.properties"/>

        <bean id="seplBean" class="cn.com.sinodata.SeplBean">
            <property name="pageSize" value="#{seplutil.pagesize}"/>
            <property name="city" value="#{valueBean.city[0]}"/>
            <property name="score" value="#{valueBean.score.math}"/>
            <property name="name" value="#{valueBean.name}"/>
        </bean>

    </beans>

(3).测试

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("sepl.xml");
SeplBean seplBean = applicationContext.getBean("seplBean", SeplBean.class);
System.out.println(seplBean.toString());

文章标题:Study(2) SpringIOC 基于xml方式依赖注入

发布时间:2020-04-23, 17:43:34

最后更新:2020-04-23, 17:43:34