Spring与IoC系列三:基于XML的依赖注入

目录

 

1.注入分类

(1)设值注入(多用)

(2)构造注入

2.命名空间注入(了解)

3.集合属性的注入(重点)

(1)为数组注入值

(2)为List注入值

(3)为Set注入值

(4)为Map注入值(key和Value是任意类型)

(5)为Properties注入值(key和Value是字符串类型类型)

4.对于域属性的自动注入

(1)byName方式自动注入

 

(2)byType方式自动注入

5.使用SPEL注入

6.使用内部Bean注入(了解)

7.使用同类抽象Bean注入(了解)

8.使用异类抽象Bean注入(了解)

9.为应用指定多个Spring配置文件(重点)

(1)平等关系的配置文件(用的多)

(2)包含关系的配置文件


1.注入分类

(1)设值注入(多用)

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

当指定bean的某属性值为另一bean的实例时,通过ref指定它们间的引用关系。ref的值必须为某bean的id值。

    <!-- 注册School -->
    <bean id="mySchool" class="com.lmm.di01.School">
    	<property name="name" value="清华大学"/>
    	<property name="score" value="695"/>
    </bean>
    
    <!-- 注册Student -->
    <bean id="myStudent" class="com.lmm.di01.Student">
    	<property name="name" value="张三"/>
    	<property name="age" value="23"/>
    	<property name="school" ref="mySchool"/>
    </bean>

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

(2)构造注入

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

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

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

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

<?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.bjpowernode.di02.School">
    	<property name="name" value="清华大学"/>
    </bean>
    
    <!-- 注册Student -->
    <bean id="myStudent" class="com.lmm.di02.Student">
    
    	<constructor-arg name="name" value="李四"/>
    	<constructor-arg name="age" value="24"/>
    	<constructor-arg name="school" ref="mySchool"/>
    	<!-- 
    	<constructor-arg index="0" value="李四"/>
    	<constructor-arg index="1" value="24"/>
    	<constructor-arg index="2" ref="mySchool"/>
    	 -->
    	<!--  
    	<constructor-arg value="李四"/>
    	<constructor-arg value="24"/>
    	<constructor-arg ref="mySchool"/>
    	 -->
    </bean>

</beans>

 

2.命名空间注入(了解)

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

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

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

这里就不详细说了~

3.集合属性的注入(重点)

package com.lmm.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 String[] myStrs;
	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 setMyStrs(String[] myStrs) {
		this.myStrs = myStrs;
	}
	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) + ", myStrs="
				+ Arrays.toString(myStrs) + ", myList=" + myList + ", mySet="
				+ mySet + ", myMap=" + myMap + ", myPros=" + myPros + "]";
	}
}

(1)为数组注入值

    	<property name="schools">
    		<array>
    			<ref bean="mySchool"/>
    			<ref bean="mySchool2"/>
    		</array>
    	</property>

(2)为List注入值

    	<property name="myList">
    		<list>
    			<value>合肥</value>
    			<value>济南</value>
    		</list>
    	</property>

(3)为Set注入值

    	<property name="mySet">
    		<set>
    			<value>安徽</value>
    			<value>合肥</value>
    		</set>
    	</property>

(4)为Map注入值(key和Value是任意类型)

    	<property name="myMap">
    		<map>
    			<entry key="mobile" value="1234567"/>
    			<entry key="QQ" value="7654321"/>
    		</map>
    	</property>

(5)为Properties注入值(key和Value是字符串类型类型)

    	<property name="myPros">
    		<props>
    			<prop key="education">大学</prop>
    			<prop key="gender">男</prop>
    		</props>
    	</property>

以上内容的简洁写法:

<?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.lmm.di06.School">
    	<property name="name" value="清华大学"/>
    </bean>
    <bean id="mySchool2" class="com.lmm.di06.School">
    	<property name="name" value="北京大学"/>
    </bean>
    
    <!-- 注册Student -->
    <bean id="mySome" class="com.lmm.di06.Some">
    	<property name="schools" ref="mySchool"/>
    	
    	<property name="myStrs" value="中国,北京"/>
    	
    	<property name="myList" value="合肥,济南"/>
    	
    	<property name="mySet" value="安徽,合肥"/>
    	
    	<property name="myMap">
    		<map>
    			<entry key="mobile" value="1234567"/>
    			<entry key="QQ" value="7654321"/>
    		</map>
    	</property>
    	
    	<property name="myPros">
    		<props>
    			<prop key="education">大学</prop>
    			<prop key="gender">男</prop>
    		</props>
    	</property>
    </bean>

</beans>

4.对于域属性的自动注入

所谓的域属性就是对象属性,如上面的School属性。那么他该如何自动注入呢?

(1)byName方式自动注入

    <!-- 注册School -->
    <bean id="school" class="com.bjpowernode.di07.School">
    	<property name="name" value="清华大学"/>
    </bean>
    
    <!-- 注册Student
    	autowire="byName" 会从容器中查找与实体类的域属性同名的Bean的id,并将该Bean对象自动注入给该域属性
     -->
    <bean id="myStudent" class="com.bjpowernode.di07.Student" autowire="byName">
    	<property name="name" value="张三"/>
    	<property name="age" value="23"/>
    </bean>

autowire="byName" 会从容器中查找与实体类的域属性同名的Bean的id,并将该Bean对象自动注入给该域属性。就是如下类中的域属性(画红线的地方),他会自动找到id=school的属性,自动注入。

 

(2)byType方式自动注入

使用byType方式自动注入,要求:配置文件中被调用者bean的class属性指定的类,要与代码中调用者Bean类的某域属性类型同源。即要么相同,要么有is-a关系(子类,或是实现类)。但这样的同源的被调用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="mySchool" class="com.lmm.di08.School">
    	<property name="name" value="清华大学"/>
    </bean>
    <!-- 
    <bean id="myPrimarySchool" class="com.bjpowernode.di08.PrimarySchool">
    	<property name="address" value="海淀区"/>
    </bean>
     -->
    <!-- 注册Student
    	autowire="byType" 会从容器中查找与实体类的域属性类型 具有is-a关系 的Bean,并将该Bean对象自动注入给该域属性
     -->
    <bean id="myStudent" class="com.lmm.di08.Student" autowire="byType">
    	<property name="name" value="张三"/>
    	<property name="age" value="23"/>
    </bean>

</beans>

5.使用SPEL注入

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

<?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="myPerson" class="com.lmm.di09.Person">
		<property name="pname" value="李四" />
		<property name="page" value="#{T(java.lang.Math).random() * 50}" />
	</bean>


	<bean id="myStudent" class="com.lmm.di09.Student">
		<property name="name" value="#{myPerson.pname}" />
		<!-- <property name="age" value="#{myPerson.page > 25 ? 25 : myPerson.page}"/> -->
		<property name="age" value="#{myPerson.computeAge() }" />
	</bean>

</beans>

其它用法:
(1) <property name=“school” value=“#{mySchool}”/>
引用另一个bean。指定school的值为另一个Bean实例mySchool。
(2) <property name=“schoolName” value=“#{mySchool.name.toUpperCase()}”/>
使用指定属性,并使用其方法。指定schoolName的值为mySchool的name属性值,并将其字母均转换为大写字母(toUpperCase()方法)。

6.使用内部Bean注入(了解)

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

    <!-- 注册Student 将school的值放到myStudent内部,其他访问不到这个bean-->
    <bean id="myStudent" class="com.lmm.di10.Student">
    	<property name="name" value="张三"/>
    	<property name="age" value="23"/>
    	<property name="school">
		    <bean class="com.lmm.di10.School">
		    	<property name="name" value="清华大学"/>
		    </bean>
    	</property>
    </bean>

7.使用同类抽象Bean注入(了解)

当若干Bean实例同属于一个类,且这些实例的属性值又有相同值时,可以使用抽象Bean,以简化配置文件。

抽象Bean是用于让其它bean继承的。这个bean在Bean类中是不能通过getBean方法获取的。设置abstract属性为true来指明该bean为抽象bean, 默认值为false。 不过,该bean不为抽象bean时,也可被继承。 只不过,在应用中,用于被继承的bean一般为抽象bean。

简化所有的其他代码

<property name="school" value="清华大学"/>
           <property name="department" value="计算机系"/>

 

令abstract="true",使得baseStudent抽象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.lmm.di11.Student" abstract="true">
    	<property name="school" value="清华大学"/>
    	<property name="department" value="计算机系"/>
    </bean>
    
    <bean id="myStudent" parent="baseStudent">
    	<property name="name" value="张三"/>
    	<property name="age" value="23"/>
    </bean>
    <bean id="myStudent2" parent="baseStudent">
    	<property name="name" value="李四"/>
    	<property name="age" value="24"/>
    </bean>
    <bean id="myStudent3" parent="baseStudent">
    	<property name="name" value="王五"/>
    	<property name="age" value="25"/>
    </bean>

</beans>

8.使用异类抽象Bean注入(了解)

当若干不同的类对象具有相同的属性,且其值也相同时,可使用异类抽象Bean。

此时baseBean不能被创建,所以parent="baseBean"

<?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="baseBean" abstract="true">
    	<property name="school" value="清华大学"/>
    	<property name="department" value="计算机系"/>
    </bean>
    
    <bean id="myStudent" class="com.lmm.di12.Student" parent="baseBean">
    	<property name="name" value="张三"/>
    	<property name="age" value="23"/>
    </bean>
    
    <bean id="myTeacher" class="com.lmm.di12.Teacher" parent="baseBean">
    	<property name="name" value="Reyco"/>
    	<property name="workAge" value="18"/>
    </bean>

</beans>

9.为应用指定多个Spring配置文件(重点)

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

(1)平等关系的配置文件(用的多)

各配置文件间为并列关系,不分主次。

调用方法:

package com.lmm.di13;

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

public class MyTest {

	@Test
	public void test01() {
		// 创建容器对象,加载Spring配置文件
		/*
		 * String resource = "com/bjpowernode/di13/spring-base.xml"; String
		 * resource2 = "com/bjpowernode/di13/spring-beans.xml";
		 * ApplicationContext ac = new ClassPathXmlApplicationContext(resource,
		 * resource2);
		 */
		/*
		 * String resource = "com/bjpowernode/di13/spring-base.xml"; String
		 * resource2 = "com/bjpowernode/di13/spring-beans.xml"; String[]
		 * resources = {resource, resource2}; ApplicationContext ac = new
		 * ClassPathXmlApplicationContext(resources);
		 */
		String resource = "com/lmm/di13/spring-*.xml";
		ApplicationContext ac = new ClassPathXmlApplicationContext(resource);

		Student student = (Student) ac.getBean("myStudent");
		System.out.println(student);

		Teacher teacher = (Teacher) ac.getBean("myTeacher");
		System.out.println(teacher);
	}

}

 

(2)包含关系的配置文件

各配置文件中有一个总文件,总配置文件将各其它子文件通过<import/>引入。在Java代码中只需要使用总配置文件对容器进行初始化即可。

<?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/bjpowernode/di14/spring-base.xml"/>
	<import resource="classpath:com/bjpowernode/di14/spring-beans.xml"/>
	 -->
	<import resource="classpath:com/lmm/di14/spring-*.xml"/>
	
</beans>
package com.lmm.di14;

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

public class MyTest {

	@Test
	public void test01() {
		// 创建容器对象,加载Spring配置文件(直接加载总的就可以)
		String resource = "com/lmm/di14/springTotal.xml";
		ApplicationContext ac = new ClassPathXmlApplicationContext(resource);

		Student student = (Student) ac.getBean("myStudent");
		System.out.println(student);

		Teacher teacher = (Teacher) ac.getBean("myTeacher");
		System.out.println(teacher);
	}

}

注意:总配置文件不能和总配置文件相同,否则通配符会通配到自己,出现错误

测试程序

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值