Spring框架第三篇之基于XML的DI注入

一、注入分类

Bean实例在调用无参构造器创建空值对象后,就要对Bean对象的属性进行初始化。初始化是由容器自动完成的,称为注入。根据注入方式的不同,常用的有两类:设值注入、构造注入、实现特定接口注入。由于第三种方式采用侵入式编程,污染代码,所以几乎不用。

1、设值注入

 设值注入是指,通过setter方法传入被调用者的实例。这种注入方式简单、直观,因而在Spring的依赖注入中大量使用。

关于设值注入举个简单的例子:

分别创建一个学校类(School):

/**
 * 学校类
 * 
 * @author Root
 */
public class School {
    
    private String name;

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

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

学生类(Student):

/**
 * 学生类
 * 
 * @author Root
 */
public class Student {

    private String name;
    private int age;
    // 对象属性,也叫做域属性
    private School school;

    public Student() {
        super();
    }

    public void setName(String name) {
        System.out.println("执行setName()");
        this.name = name;
    }

    public void setAge(int age) {
        System.out.println("执行setAge()");
        this.age = age;
    }

    public void setSchool(School school) {
        this.school = school;
    }

    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + ", school=" + school + "]";
    }

}

在配置文件中使用设值注入方式,设值对象属性值:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- 注册School -->
    <bean id="school" class="com.ietree.spring.basic.di.setter.School">
        <property name="name" value="北京大学"></property>
    </bean>
    
    <!-- 注册Student -->
    <bean id="student" class="com.ietree.spring.basic.di.setter.Student">
        <property name="name" value="李华"></property>
        <property name="age" value="20"></property>
        <!-- 域属性注入使用ref -->
        <property name="school" ref="school"></property>
    </bean>
    
</beans>

注意:如果对象中包含有另外的对象引用,则需要使用ref,而不能使用value。

测试:

@Test
public void test01(){
        
    String resource = "com/ietree/spring/basic/di/setter/applicationContext.xml";
    ApplicationContext ctx = new ClassPathXmlApplicationContext(resource);
        
    Student student = (Student) ctx.getBean("student");
    System.out.println(student);
}

程序输出:

执行setName()
执行setAge()
Student [name=李华, age=20, school=School [name=北京大学]]

2、构造注入

 构造注入,顾名思义就是通过构造方法注入,举个简单的例子:

创建一个学校类(School):

/**
 * 学校类
 * 
 * @author Root
 */
public class School {
    
    private String name;

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

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

学生类(Student):

/**
 * 学生类
 * 
 * @author Root
 */
public class Student {

    private String name;
    private int age;
    // 对象属性,也叫做域属性
    private School school;

    /*public Student() {
        super();
    }*/

    // 代参构造器
    public Student(String name, int age, School school) {
        super();
        this.name = name;
        this.age = age;
        this.school = school;
    }

    public void setName(String name) {
        System.out.println("执行setName()");
        this.name = name;
    }

    public void setAge(int age) {
        System.out.println("执行setAge()");
        this.age = age;
    }

    public void setSchool(School school) {
        this.school = school;
    }

    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + ", school=" + school + "]";
    }

}

配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- 注册School -->
    <bean id="school" class="com.ietree.spring.basic.di.constructor.School">
        <property name="name" value="北京大学"></property>
    </bean>
    
    <!-- 注册Student -->
    <!-- 方式一 -->
    <!-- <bean id="student" class="com.ietree.spring.basic.di.constructor.Student">
        <constructor-arg index="0" value="李华"/>
        <constructor-arg index="1" value="20"/>
        <constructor-arg index="2" ref="school"/>
    </bean> -->
    
    <!-- 方式二 -->
    <!-- <bean id="student" class="com.ietree.spring.basic.di.constructor.Student">
        <constructor-arg value="李华"/>
        <constructor-arg value="20"/>
        <constructor-arg ref="school"/>
    </bean> -->
    
    <!-- 方式三:推荐-->
    <bean id="student" class="com.ietree.spring.basic.di.constructor.Student">
        <constructor-arg name="name" value="李华"/>
        <constructor-arg name="age" value="20"/>
        <constructor-arg name="school" ref="school"/>
    </bean>
    
</beans>

个人强烈推荐使用方式三,因为这样的配置方式不会带来歧义,关键是可读性比强两者要强。

测试:

@Test
public void test01(){
        
    String resource = "com/ietree/spring/basic/di/constructor/applicationContext.xml";
    ApplicationContext ctx = new ClassPathXmlApplicationContext(resource);
        
    Student student = (Student) ctx.getBean("student");
    System.out.println(student);
}

程序输出:

Student [name=李华, age=20, school=School [name=北京大学]]

二、命名空间注入

 命名空间注入分为两种,p命名空间和c命名空间。

例:

创建School类:

/**
 * 学校类
 * 
 * @author Root
 */
public class School {
    
    private String name;

    public School(String name) {
        super();
        this.name = name;
    }

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

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

创建学生类(Student):

/**
 * 学生类
 * 
 * @author Root
 */
public class Student {

    private String name;
    private int age;
    // 对象属性,也叫做域属性
    private School school;

    public Student() {
        super();
    }

    public Student(String name, int age, School school) {
        super();
        this.name = name;
        this.age = age;
        this.school = school;
    }

    public void setName(String name) {
        System.out.println("执行setName()");
        this.name = name;
    }

    public void setAge(int age) {
        System.out.println("执行setAge()");
        this.age = age;
    }

    public void setSchool(School school) {
        this.school = school;
    }

    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + ", school=" + school + "]";
    }

}

配置文件:

<?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:p="http://www.springframework.org/schema/p"
    
    xmlns:c="http://www.springframework.org/schema/c"
    
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- 注册School -->
    <!-- <bean id="mySchool" class="com.ietree.spring.basic.di.namespace.School" p:name="清华大学"/>
    
    注册Student
    <bean id="student" class="com.ietree.spring.basic.di.namespace.Student" p:name="李华" p:age="20" p:school-ref="mySchool"/> -->
    
    <!-- 注册School -->
    <bean id="mySchool" class="com.ietree.spring.basic.di.namespace.School" c:name="清华大学"/>
    
    <!-- 注册Student -->
    <bean id="student" class="com.ietree.spring.basic.di.namespace.Student" c:name="李华" c:age="20" c:school-ref="mySchool"/>
    
</beans>

注意:

1、这里如果要想使用这两种命名空间方式的话,需要先导入约束:

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

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

2、如果是使用c命名空间的方式的话,在类里面还必须写上带参构造器。

三、集合属性注入

 创建School类:

/**
 * 学校类
 * 
 * @author Root
 */
public class School {
    
    private String name;

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

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

创建Some类:

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 String[] myStr;
    private List<String> myList;
    private Set<String> mySet;
    private Map<String, Object> myMap;
    private Properties myProps;

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

    public void setMyStr(String[] myStr) {
        this.myStr = myStr;
    }

    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 setMyProps(Properties myProps) {
        this.myProps = myProps;
    }

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

}

配置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"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- 注册School -->
    <bean id="mySchool" class="com.ietree.spring.basic.di.list.School">
        <property name="name" value="北京大学"></property>
    </bean>
    <bean id="mySchool2" class="com.ietree.spring.basic.di.list.School">
        <property name="name" value="清华大学"></property>
    </bean>
    
    <!-- 注册Student -->
    <bean id="some" class="com.ietree.spring.basic.di.list.Some">
        <property name="schools">
            <array>
                <ref bean="mySchool"/>
                <ref bean="mySchool2"/>
            </array>
        </property>
        <property name="myStr">
            <array>
                <value>中国</value>
                <value>广东</value>
            </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="mobile" value="123456"></entry>
                <entry key="weChat" value="654321"></entry>
            </map>
        </property>
        <property name="myProps">
            <props>
                <prop key="edu">本科</prop>
                <prop key="gender">性别</prop>
            </props>
        </property>
    </bean>
    
</beans>

方式二:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- 注册School -->
    <bean id="mySchool" class="com.ietree.spring.basic.di.list.School">
        <property name="name" value="北京大学"></property>
    </bean>
    <bean id="mySchool2" class="com.ietree.spring.basic.di.list.School">
        <property name="name" value="清华大学"></property>
    </bean>
    
    <!-- 注册Student -->
    <bean id="some" class="com.ietree.spring.basic.di.list.Some">
        <property name="schools">
            <array>
                <ref bean="mySchool"/>
                <ref bean="mySchool2"/>
            </array>
        </property>
        
        <property name="myStr" value="中国,广东"/>
        
        <property name="myList" value="深圳,龙岗"/>
        
        <property name="mySet" value="坂田,天安云谷"/>
        
        <property name="myMap">
            <map>
                <entry key="mobile" value="123456"></entry>
                <entry key="weChat" value="654321"></entry>
            </map>
        </property>
        <property name="myProps">
            <props>
                <prop key="edu">本科</prop>
                <prop key="gender">性别</prop>
            </props>
        </property>
    </bean>
    
</beans>

四、对于域属性的自动注入

 

<!-- 注册Student 
        autowire="byName":通过字段名注入
        autowire="byType":通过字段类型注入
-->
<bean id="student" class="com.ietree.spring.basic.di.domain.Student" autowire="byName">
    <property name="name" value="李华"></property>
    <property name="age" value="20"></property>
</bean>

五、使用SPEL注入

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

举例:

创建Person类:

package com.ietree.spring.basic.di.spel;

public class Person {

    private String pname;

    private int page;

    public Person() {
        super();
    }

    public void setPname(String pname) {
        this.pname = pname;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public String getPname() {
        return pname;
    }

    public int getPage() {
        return page;
    }
    
    public int computeAge() {
        return this.page > 25 ? 25 : this.page;
    }
    
    @Override
    public String toString() {
        return "Person [pname=" + pname + ", page=" + page + "]";
    }

}

创建Student类:

package com.ietree.spring.basic.di.spel;

/**
 * 学生类
 * 
 * @author Root
 */
public class Student {

    private String name;

    private int age;

    public Student() {
        super();
    }

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

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

    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + "]";
    }

}

配置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"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean id="myPerson" class="com.ietree.spring.basic.di.spel.Person">
        <property name="pname" value="李华"></property>
<!-- 随机生成0 - 99数字 -->
<property name="page" value="#{T(java.lang.Math).random() * 100}"></property> </bean> <bean id="myStudent" class="com.ietree.spring.basic.di.spel.Student"> <property name="name" value="#{myPerson.pname}"></property> <!-- <property name="age" value="#{myPerson.page > 25 ? 25 : myPerson.page}"></property> --> <property name="age" value="#{myPerson.computeAge() }"></property> </bean> </beans>

 

六、使用内部Bean注入

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- 注册School -->
    <!-- <bean id="school" class="com.ietree.spring.basic.di.inner.School">
        <property name="name" value="北京大学"></property>
    </bean> -->
    
    <!-- 注册Student -->
    <bean id="student" class="com.ietree.spring.basic.di.inner.Student">
        <property name="name" value="李华"></property>
        <property name="age" value="20"></property>
        <property name="school">
            <bean class="com.ietree.spring.basic.di.inner.School">
                <property name="name" value="清华大学"></property>
            </bean>
        </property>
    </bean>
    
</beans>

 

七、使用同类抽象Bean注入

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- 同类抽象Bean -->
    <bean id="baseStudent" class="com.ietree.spring.basic.di.sameextends.Student" abstract="true">
        <property name="school" value="清华大学"/>
        <property name="department" value="计算机系"/>
    </bean>
    <bean id="student1" parent="baseStudent">
        <property name="name" value="小明"/>
        <property name="age" value="21"/>
    </bean>
    <bean id="student2" parent="baseStudent">
        <property name="name" value="张三"/>
        <property name="age" value="22"/>
    </bean>
    <bean id="student3" parent="baseStudent">
        <property name="name" value="李四"/>
        <property name="age" value="23"/>
    </bean>
    
</beans>

 

八、使用异类抽象Bean注入

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- 异类抽象Bean -->
    <bean id="baseStudent" abstract="true">
        <property name="school" value="清华大学"/>
        <property name="department" value="计算机系"/>
    </bean>
    
    <bean id="student" class="com.ietree.spring.basic.di.sameextends.Student" parent="baseStudent">
        <property name="name" value="小明"/>
        <property name="age" value="21"/>
    </bean>
    <bean id="teacher" class="com.ietree.spring.basic.di.sameextends.Teacher" parent="baseStudent">
        <property name="name" value="李四"/>
        <property name="age" value="23"/>
    </bean>
    
</beans>

 

九、为应用指定多个Spring配置文件

 1、同级关系:

测试:

package com.ietree.spring.basic.di.mulxml;

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

public class MyTest {

    @Test
    public void test01() {

        /*String resource1 = "com/ietree/spring/basic/di/setter/spring-base.xml";
        String resource2 = "com/ietree/spring/basic/di/setter/spring-beans.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(resource1, resource2);*/
        
        String resource = "com/ietree/spring/basic/di/setter/spring-*.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(resource);

        Student student = (Student) ctx.getBean("student");
        System.out.println(student);
    }

}

2、包含关系:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <import resource="classpath:com/ietree/spring/basic/di/mulxml/spring-base.xml"/>
    <import resource="classpath:com/ietree/spring/basic/di/mulxml/spring-beans.xml"/>
</beans>

 

posted @ 2017-06-18 21:41  远近啊  阅读(389)  评论(0编辑  收藏  举报