3.Spring与IoC-基于XML的依赖注入(DI)

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

记住:所有的Bean类都要注册到配置文件里!!!

设值注入

通过setter方法传入被调用者的实例(大量使用),这种注入方式简单、直观。

实体类

public class Student {
    private String name;
    private int age;
    private School school;  //域属性,对象属性

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

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

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}
public class School {
    private String name;

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

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

配置文件

<!--注册School-->
    <bean id="mySchool" class="com.chen.service.School">
        <property name="name" value="university"/>
    </bean>
    <!--注册Student-->
    <bean id="myStudent" class="com.chen.service.Student">
        <property name="name" value="allen"/>
        <property name="age" value="24"/>
        <property name="school" ref="mySchool"/>
    </bean>

测试

	 @Test
    public void testStudent() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Student student = (Student) ac.getBean("myStudent");
        System.out.println(student);

    }

结果:

Student{name='allen', age=24, school=School{name='university'}}

构造注入

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

第一种形式

实体类

	public class Student2 {
    private String name;
    private int age;
    private School school;  //域属性,对象属性

    public Student2() {
    }

    public Student2(String name, int age, School school) {
        this.name = name;
        this.age = age;
        this.school = school;
	}
	//setter()方法
}

配置文件

	<!--注册Student2-->
    <bean id="myStudent2" class="com.chen.service.Student2">
        <constructor-arg index="0" value="Chen"/>
        <constructor-arg index="1" value="24"/>
        <constructor-arg index="2" ref="mySchool"/>
    </bean>

测试

	 @Test
    public void testStudent2() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Student2 student2 = (Student2) ac.getBean("myStudent2");
        System.out.println(student2);
    }

结果

Student2{name='Chen', age=24, school=School{name='清华大学'}}

第二种形式(构造注入中最常用的方式,但是工作中最常用的注入方式是设值注入)
配置文件中的修改

	<bean id="myStudent2" class="com.chen.service.Student2">
		<constructor-arg name="name" value="allen"/>
		<constructor-arg name="age" value="24"/>
		<constructor-arg name="school" ref="mySchool"/>
	</bean>

命名空间注入(仅作了解)
  • p命名空间设值注入:采用设值注入方式,故需要哟uxiangying的setter()方法
  • c命名空间构造注入:采用构造注入方式,故需要有相应的构造器

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


集合属性注入(重点)

方式一(繁杂)

实体类

public class Collections {
    private School[] schools;
    private String[] myStrs;
    private List<String> myList;
    private Set<String> mySet;
    private Map<String, Object> myMap;
    private Properties myProperties;
	
	//setter()/toString()方法
}

配置文件

	<!--注册School-->
    <bean id="mySchool" class="com.chen.service.School">
        <property name="name" value="清华大学"/>
    </bean>
    <bean id="mySchool2" class="com.chen.service.School">
        <property name="name" value="北京大学"/>
    </bean>
	<!--注册Collections-->
    <bean id="myCollections" class="com.chen.service.Collections">
        <property name="schools">
            <array>
                <ref bean="mySchool"/>
                <ref bean="mySchool2"/>
            </array>
        </property>
        <property name="myStrs">
            <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="1234"/>
                <entry key="mobile2" value="5667"/>
            </map>
        </property>
        <property name="myProperties">
            <props >
                <prop key="education">university</prop>
                <prop key="gender">male</prop>
            </props>
        </property>
    </bean>

测试

	@Test
    public void testCollections() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Collections collections = (Collections) ac.getBean("myCollections");
        System.out.println(collections);
    }

结果

Collections{schools=[School{name='清华大学'}, School{name='北京大学'}], myStrs=[北京, 上海], myList=[深圳, 杭州], mySet=[成都, 重庆], myMap={mobile=1234, mobile2=5667}, myProperties={gender=male, education=university}}

方式二(较为简单的方式)
修改xml配置文件即可

	<!--注册School-->
    <bean id="mySchool" class="com.chen.service.School">
        <property name="name" value="清华大学"/>
    </bean>
    <bean id="mySchool2" class="com.chen.service.School">
        <property name="name" value="北京大学"/>
    </bean>
	
	<!--注册Collections-->
    <bean id="myCollections" class="com.chen.service.Collections">
        <property name="schools">
            <array>
                <ref bean="mySchool"/>
                <ref bean="mySchool2"/>
            </array>
        </property>
        <property name="myStrs" value="北京, 上海"/>   
        <property name="myList" value="深圳, 杭州"/>
        <property name="mySet" value="成都, 重庆"/>
        <property name="myMap">
            <map>
                <entry key="mobile" value="1234"/>
                <entry key="mobile2" value="5667"/>
            </map>
        </property>
        <property name="myProperties">
            <props >
                <prop key="education">university</prop>
                <prop key="gender">male</prop>
            </props>
        </property>
    </bean>

使用SPEL注入

spel,Spring Expression Langurage,即Spring EL表达式语言。

在Spring配置文件中为Bean的属性注入值时,可直接使用SPEL表达式计算的结果。SPEL表达式以#开头,后跟一对大括号。用法:<bean id=“abc” value="#{…}"/>。

实体类

public class Person {
    private String pname;
    private int page;
	//getter()/setter()/toString()
}
public class Student3 {
    private String name;
    private int age;
	//getter()/setter()/toString()
}

xml配置

	<!--注册Person-->
    <bean id="myPerson" class="com.chen.service.Person">
        <property name="pname" value="Wang"/>
        <property name="page" value="#{T(java.lang.Math).random() * 50}"/>
    </bean>
    <!--注册Student3-->
    <bean id="myStudent3" class="com.chen.service.Student3">
        <property name="name" value="#{myPerson.pname}"/>
        <property name="age" value="#{myPerson.page > 25 ? 25 : myPerson.page}"/>
    </bean>

测试类

	@Test
    public void testSPEL() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person = (Person) ac.getBean("myPerson");
        System.out.println(person);
        Student3 student3 = (Student3) ac.getBean("myStudent3");
        System.out.println(student3);
    }

测试结果

Person{pname='Wang', page=27}
Student3{name='Wang', age=25}

以下三个内容仅作了解


1、使用内部Bean注入
	<bean id="myStudent" class="com.chen.service.Student">
		<property name="name" value="allen"/>
		<property name="age" value="24"/>
		<property name="school">
			<bean class="com.chen.service.School">
				<property name="name" value="清华大学"/>
		</property>
	</bean>
2、同类抽象Bean

实体类

public class Student4 {
    String name;
    int age;
    String school;
    String department;

	//getter()/setter()/toString()
}

xml配置

	<!-- ==================== 同类抽象Bean =================================== -->
	<!--注册Student4-->
    <bean id="baseStudent4" class="com.chen.service.Student4" abstract="true">
        <property name="school" value="清华大学"/>
        <property name="department" value="计算机学院"/>
    </bean>

    <bean id="myStudent4_1" parent="baseStudent4">
        <property name="name" value="allen"/>
        <property name="age" value="24"/>
    </bean>
    <bean id="myStudent4_2" parent="baseStudent4">
        <property name="name" value="wang"/>
        <property name="department" value="27"/>
    </bean>
    <bean id="myStudent4_3" parent="baseStudent4">
        <property name="name" value="Hao"/>
        <property name="age" value="24"/>
    </bean>

测试

	@Test
    public void testStudent4() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Student4 student4_1 = (Student4)ac.getBean("myStudent4_1");
        Student4 student4_2 = (Student4)ac.getBean("myStudent4_2");
        Student4 student4_3 = (Student4) ac.getBean("myStudent4_3");
        System.out.println(student4_1);
        System.out.println(student4_2);
        System.out.println(student4_3);
    }

结果

Student4{name='allen', age=24, school='清华大学', department='计算机学院'}
Student4{name='wang', age=27, school='清华大学', department='计算机学院'}
Student4{name='Hao', age=24, school='清华大学', department='计算机学院'}
3、异类抽象Bean

实体类

	public class Teacher {
    private String name;
    private int workage;    //工龄
    private String school;  //学校
    private String department;  //院系

	//getter()/setter()/toString()
}
	public class Student5 {
    String name;
    int age;
    String school;
    String department;
	//getter()/setter()/toString()
}

xml配置

	<!-- ==================== 异类抽象Bean =================================== -->
    <bean id="baseBean" abstract="true">
        <property name="school" value="清华大学"/>
        <property name="department" value="计算机系"/>
    </bean>
    <bean id="myStudent5" class="com.chen.service.Student5" parent="baseBean">
        <property name="name" value="alen walker"/>
        <property name="age" value="20"/>
    </bean>
    <!--注册Teacher-->
    <bean id="myTeacher" class="com.chen.service.Teacher" parent="baseBean">
        <property name="name" value="Zhang"/>
        <property name="workage" value="18"/>
    </bean>

测试

	@Test
    public void testTeacher() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Student5 student5 = (Student5)ac.getBean("myStudent5");
        Teacher teacher = (Teacher)ac.getBean("myTeacher");
        System.out.println(student5);
        System.out.println(teacher);
    }

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

在实际应用里,随着应用规模的增加,系统中Bean数量也大量增加,导致配置文件变的非常庞大,臃肿。为了避免这种情况的产生,提高配置文件的可读性与可维护性,可以将Spring配置文件分解成多个配置文件。

  1. 平等关系的配置文件(用的是最多的)
    将配置文件分解为地位平等的多个配置文件,并将所有配置文件的路径定义为一个String数组,将其作为容器初始化参数出现。其将与可变参的容器构造器匹配。

配置文件
spring-base.xml

	<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="baseBean" abstract="true">
        <property name="school" value="清华大学"/>
        <property name="department" value="计算机系"/>
    </bean>

spring-beans.xml

	<bean id="myStudent5" class="com.chen.service.Student5" parent="baseBean">
        <property name="name" value="alen walker"/>
        <property name="age" value="20"/>
    </bean>
    <!--注册Teacher-->
    <bean id="myTeacher" class="com.chen.service.Teacher" parent="baseBean">
        <property name="name" value="Zhang"/>
        <property name="workage" value="18"/>
    </bean>

测试

	@Test
    public void testMultipyXml() {
        /*
            第一种方式
            String resource1 = "spring-base.xml";
            String resource2 = "spring-beans.xml";
            ApplicationContext ac = new ClassPathXmlApplicationContext(resource1, resource2);
         */
        /*
            第二种方式
            String[] resource = {"spring-base.xml", "spring-beans.xml"};
            ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
         */
        /*
            第三种方式(项目常用方式)
            String resource = "spring-*.xml";
            ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
         */
        String resource = "spring-*.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
        Student5 student5 = (Student5) ac.getBean("myStudent5");
        Teacher teacher = (Teacher) ac.getBean("myTeacher");
        System.out.println(student5);
        System.out.println(teacher);
    }
  1. 包含关系

xml配置文件
applcationContext1.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">
    <import resource="classpath:spring-base.xml"/>
    <import resource="classpath:spring-beans.xml"/>
</beans>

spring-base.xml

	<bean id="baseBean" abstract="true">
        <property name="school" value="清华大学"/>
        <property name="department" value="计算机系"/>
    </bean>

spring-beans.xml

	<bean id="myStudent5" class="com.chen.service.Student5" parent="baseBean">
        <property name="name" value="alen walker"/>
        <property name="age" value="20"/>
    </bean>
    <!--注册Teacher-->
    <bean id="myTeacher" class="com.chen.service.Teacher" parent="baseBean">
        <property name="name" value="Zhang"/>
        <property name="workage" value="18"/>
    </bean>

测试

	@Test
    public void testContains() {
        String resource = "applicationContext1.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
        Student5 student5 = (Student5) ac.getBean("myStudent5");
        Teacher teacher = (Teacher) ac.getBean("myTeacher");
        System.out.println(student5);
        System.out.println(teacher);
    }

结果

Student4{name='alen walker', age=20, school='清华大学', department='计算机系'}
Teacher{name='Zhang', workage=18, school='清华大学', department='计算机系'}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值