[Js-Spring]基于 XML 的 DI

Posted Js_zero

tags:

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

注入分类

(1)设值注入:先调用 Bean 的无参构造函数,然后通过 setter 方法传入被调用者的实例。

<!-- bean definitions here -->
<bean id="mySchool" class="com.neu.di01.School">
    <property name="sname" value="neu"></property>
</bean>
<bean id="myStudent" class="com.neu.di01.Student">
    <property name="name" value="js"></property>
    <property name="age" value="23"></property>
    <property name="school" ref="mySchool"></property>
</bean>

注:对于其他 Bean 对象的引用,除了<bean/>标签的 ref 属性外,还可以使用 <ref/> 标签

(2)构造注入:在构造调用者实例的同时,完成了被调用者的实例化。即使用构造器设置依赖关系

<constructor-arg> 标签中用于指定参数的属性:

name:指定参数名称

index:指明该参数对应构造器的第几个参数,从0开始,不过该属性可以不需要,但是需要注意,若参数类型相同,或之间有包含关系,则需要保证赋值顺序要与构造器中的参数顺序一致

   另外,type属性可用于指定类型,基本类型直接写类型关键字即可,非基本类型需要写全限定性类名

<!-- bean definitions here -->
<bean id="mySchool" class="com.neu.di02.School">
    <property name="sname" value="neu"></property>
</bean>
<bean id="myStudent" class="com.neu.di02.Student">
    <constructor-arg name="name" value="js"></constructor-arg>
    <constructor-arg name="age" value="22"></constructor-arg>
    <constructor-arg name="school" ref="mySchool"></constructor-arg>
    <!-- 
    <constructor-arg value="js"></constructor-arg>
    <constructor-arg value="22"></constructor-arg>
    <constructor-arg ref="mySchool"></constructor-arg>
     -->
    <!-- 
    <constructor-arg index="0" value="js"></constructor-arg>
    <constructor-arg index="1" value="22"></constructor-arg>
    <constructor-arg index="2" ref="mySchool"></constructor-arg>
     -->
</bean>

(3)特定接口注入:采用了侵入式编程,污染了代码,几乎不用

 命名空间注入(了解)

对于设值注入和构造注入,除了使用 <property/>或<constructor-arg/>标签外,还可以使用命名空间注入的方式,让注入的值以<bean/>标签属性的方式出现。根据注入实现方式的不同,分别以 p 命名空间和 c 命名空间注入。

p 命名空间注入:采用设值注入,需要相应的 setter 方法

c 命名空间注入:采用构造注入,需要相应的构造器

(1)p 命名空间注入

采用约束

xmlns:p="http://www.springframework.org/schema/p"

 

<!-- bean definitions here -->
<bean id="mySchool" class="com.neu.di03.School" p:sname="北京大学"></bean>
<bean id="myStudent" class="com.neu.di03.Student" p:name="张三"
    p:age="22" p:school-ref="mySchool"></bean>

 

(2)c 命名空间注入

采用约束

xmlns:c="http://www.springframework.org/schema/c"

 

<!-- bean definitions here -->
<bean id="mySchool" class="com.neu.di04.School">
    <property name="sname" value="清华大学"></property>
</bean>
<bean id="myStudent" class="com.neu.di04.Student" c:name="张三"
    c:age="22" c:school-ref="mySchool"></bean>

 

集合属性注入

 分别为数组,List,Set,Map,Properties注入值,例子如下,

School.java

package com.neu.di05;

public class School {
    private String sname;

    public void setSname(String sname) {
        this.sname = sname;
    }

    @Override
    public String toString() {
        return "School [sname=" + sname + "]";
    }
}

Some.java

package com.neu.di05;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class Some {
    private School[] schools;
    private List<String> myList;
    private Set<String> mySet;
    private Map<String, Object> myMap;
    private Properties myPros;

    public void setSchools(School[] schools) {
        this.schools = schools;
    }

    public void setMyList(List<String> myList) {
        this.myList = myList;
    }

    public void setMySet(Set<String> mySet) {
        this.mySet = mySet;
    }

    public void setMyMap(Map<String, Object> myMap) {
        this.myMap = myMap;
    }

    public void setMyPros(Properties myPros) {
        this.myPros = myPros;
    }

    @Override
    public String toString() {
        return "Some [schools=" + Arrays.toString(schools) + ", myList=" + myList + ", mySet=" + mySet + ", myMap="
                + myMap + ", myPros=" + myPros + "]";
    }

}

applicationContext.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:c="http://www.springframework.org/schema/c"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">

    <!-- bean definitions here -->
    <bean id="school1" class="com.neu.di05.School">
        <property name="sname" value="清华大学"></property>
    </bean>
    <bean id="school2" class="com.neu.di05.School">
        <property name="sname" value="北京大学"></property>
    </bean>
    <bean id="some" class="com.neu.di05.Some">
        <property name="schools">
            <array>
                <ref bean="school1" />
                <ref bean="school2" />
            </array>
        </property>
        <property name="myList">
            <list>
                <value>张三</value>
                <value>李四</value>
            </list>
        </property>
        <property name="mySet">
            <set>
                <value>北京</value>
                <value>上海</value>
            </set>
        </property>
        <property name="myMap">
            <map>
                <entry key="QQ" value="123"></entry>
                <entry key="WeiXin" value="456"></entry>
            </map>
        </property>
        <property name="myPros">
            <props>
                <prop key="地址">辽宁省沈阳市</prop>
                <prop key="名称">neu</prop>
            </props>
        </property>
    </bean>

</beans>

 

applicationContext.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:c="http://www.springframework.org/schema/c"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">

    <!-- bean definitions here -->
    <bean id="school1" class="com.neu.di06.School">
        <property name="sname" value="清华大学"></property>
    </bean>
    <bean id="school2" class="com.neu.di06.School">
        <property name="sname" value="北京大学"></property>
    </bean>
    <bean id="some" class="com.neu.di06.Some">
        <property name="schools">
            <array>
                <ref bean="school1" />
                <ref bean="school2" />
            </array>
        </property>
        <property name="arrays" value="aaa,bbb"></property>
        <property name="myList" value="张三s,李四"></property>
        <property name="mySet" value="北京,上海"></property>
        <property name="myMap">
            <map>
                <entry key="QQ" value="123"></entry>
                <entry key="WeiXin" value="456"></entry>
            </map>
        </property>
        <property name="myPros">
            <props>
                <prop key="地址">辽宁省沈阳市</prop>
                <prop key="名称">neu</prop>
            </props>
        </property>
    </bean>

</beans>

 

MyTest.java

package com.neu.di05;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {

    @Test
    public void test01() {
        // 加载Spring配置文件,创建Spring容器对象
        String resource = "com/neu/di05/applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
        // 从容器中获取指定的Bean对象
        Some some = (Some) ac.getBean("some");
        System.out.println(some);
        ((ClassPathXmlApplicationContext) ac).close();
    }
}

 

对于域属性的自动注入

byName 方式自动注入

配置文件中被调用者的 Bean 的 id 值与代码中调用者 Bean 的属性名相同时,可以使用 byName 的方式,让容器自动将被调用者 Bean 注入给调用者 Bean 。

如图中 id 为 school 的 Bean,正好对应 Student 类中定义的 school 成员变量,在 id 为 myStudent 的 Bean 中直接定义自动注入方式 autowrite=“byName” 即可

byType 方式自动注入

配置文件中被调用者Bean的class属性指定的类,必须要与代码中被调用者Bean类的某域属性同源,即,相同或者具有is-a关系(子类,或者实现类)。同源的被调用者Bean只能有一个,多于一个则会报错,不知道该匹配哪一个。

使用SPEL表达式

SPEL(Spring Expression Language),即 Spring EL 表达式语言。即,在 Spring 配置文件中为 Bean 的属性注入值的时候,可以直接使用 SPEL 表达式计算结果。SPEL表达式以#开头,后加一对大括号。

用法:<bean id="abc" value="#{…}" />。

Person.java

package com.neu.di10;

public class Person {
    private String pname;
    private int page;

    // getter and setter

    // 计算年龄,大于25岁则按照25岁计算
    public int computeAge() {
        return this.page > 25 ? 25 : this.page;
    }
    
    // toString

}

 

Student.java

package com.neu.di10;

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

    // getter and setter

    // toString

}

 

applicationContext.xml 中的配置

<bean id="myPerson" class="com.neu.di10.Person">
    <property name="pname" value="wx"></property>
    <property name="page" value="#{T(java.lang.Math).random()*50}"></property>
</bean>
<bean id="myStudent" class="com.neu.di10.Student">
    <property name="name" value="#{myPerson.pname}"></property>
    <property name="age" value="#{myPerson.computeAge()}"></property>
<!-- <property name="age" value="#{myPerson.page>25?25:myPerson.page}"></property> -->
</bean>

 

上面仅仅是个例子,具体详细的所有用法可以查看框架解压包下面的 spring-framework-4.2.1.RELEASE\\docs\\spring-framework-reference\\htmlsingle\\index.html 中查找 SPEL 用法

框架包百度云链接 密码是 ycgm

使用内部 Bean 注入

当我们不希望代码直接访问某个 bean,即在代码中通过 getBean 方法获取该 Bean 实例,则可以将该 Bean 的定义放入调用者 bean 定义的内部,例子,

匿名 Bean(虽然无法在代码中通过 getBean() 方法获取,但是可以通过类型自动注入)

<!-- 匿名Bean -->
<bean class="com.neu.di11.School">
    <property name="sname" value="neu"></property>
</bean>
<bean id="myStudent" class="com.neu.di11.Student" autowire="byType">
    <property name="name" value="js"></property>
    <property name="age" value="23"></property>
</bean>

 

内部匿名Bean

<!-- 内部匿名bean -->
<bean id="myStudent" class="com.neu.di12.Student" autowire="byType">
    <property name="name" value="js"></property>
    <property name="age" value="23"></property>
    <property name="school">
        <bean class="com.neu.di12.School">
            <property name="sname" value="neu"></property>
        </bean>
    </property>
</bean>

 

使用同类抽象 Bean 注入

当若干的 Bean 实例同属于一个类,这些实例的属性值又有相同值,我们考虑使用抽象 Bean 来避免冗余,简化配置文件

抽象 Bean 是用于让其他的 bean 继承的。这个 bean 不能通过 getBean() 方法来获取,所以应该设置 abstract 属性为 true,其默认值是 false(不设置为抽象 Bean 也能被继承,但一般应该设置为抽象的)

Student 的部分代码

public class Student {
    private String name;
    private int age;
    private String school;
    private String department;

 

<!-- 同类抽象Bean -->
<bean id="baseStudent" class="com.neu.di13.Student" abstract="true">
    <property name="school" value="清华大学"></property>
    <property name="department" value="计算机学院"></property>
</bean>
<bean id="student1" parent="baseStudent">
    <property name="name" value="JS"></property>
    <property name="age" value="21"></property>
</bean>
<bean id="student2" parent="baseStudent">
    <property name="name" value="WY"></property>
    <property name="age" value="22"></property>
</bean>
<bean id="student3" parent="baseStudent">
    <property name="name" value="WX"></property>
    <property name="age" value="20"></property>
</bean>

 

使用异类抽象 Bean 注入

这种注入应用的情况是若干不同类的对象具有相同的属性,值也相同时。

Student 类的成员变量如之前的同类抽象一样

这是 Teacher 的部分代码(年龄变成了工龄)

public class Teacher {
    private String name;
    private int workAge;
    private String school;
    private String department;