三大组件之Spring第二章 基于XML和注解的DI

XML的设置注入与域属性注入

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

更多的使用设置注入,而非构造注入
03di package com.bjpowernode.di01;
学生类

public class Student {
	private String name;
	private int age;
	private 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 + "]";
	}
}

学校类

public class School {
	private String name;

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

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

测试类

public class MyTest {
		
	@Test
	public void test01() {
		
		//创建容器对象,加载Spring配置文件
		//会从类路径src下查找配置文件
		//底层反射调用的是无参构造器new instance 如果写有参构造会屏蔽掉无参构造 导致初始化失败
		
		String resource = "com/bjpowernode/di01/applicationContext.xml";
		ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
		Student student = (Student) ac.getBean("myStudent");
		System.out.println(student);
		
	}
	
	
}

配置文件

<!-- 注册School  -->
    <bean id="mySchool" class="com.bjpowernode.di01.School">
    <property name="name" value="清华大学"/>

	</bean>
	
    <!-- 注册Student  -->
    <bean id="myStudent" class="com.bjpowernode.di01.Student">
    <property name="name" value="张三"/>
    <property name="age" value="23"/>
    <property name="school" ref="mySchool"/>
	
	</bean>

注意普通成员变量与域属性注册的方式不同

结果:执行setName()方法
执行setAge()方法
Student [name=张三, age=23, school=School [name=清华大学]]

构造注入

03di package com.bjpowernode.di02;
用的少
学生类

public class Student {
	private String name;
	private int age;
	private School school;  //对象属性,域属性
	
	public Student(String name, int age, School school) {
		super();
		this.name = name;
		this.age = age;
		this.school = school;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + ", school=" + school + "]";
	}

	

}

学校类不变
测试类不变
配置文件

</bean>

<!-- 注册Student  -->
<bean id="myStudent" class="com.bjpowernode.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>

集合属性注入(重要,但不建议用这种写法)

03di package com.bjpowernode.di05;
学校类不变

public class School {
	private String name;

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

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

学生类

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 + "]";
	}
	
	
}

重点在于注册配置文件

<!-- 注册School  -->
    <bean id="mySchool" class="com.bjpowernode.di05.School">
    <property name="name" value="清华大学"/>

	</bean>
	
    <bean id="mySchool2" class="com.bjpowernode.di05.School">
    <property name="name" value="北京大学"/>

	</bean>
	
    <!-- 注册Some  -->
    <bean id="mySome" class="com.bjpowernode.di05.Some">
    <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>10号楼</value>	
		</set>
			
	</property>
	
	<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>

测试类

@Test
	public void test01() {
		
		//创建容器对象,加载Spring配置文件
		//会从类路径src下查找配置文件
		//底层反射调用的是无参构造器new instance 如果写有参构造会屏蔽掉无参构造 导致初始化失败
		
		String resource = "com/bjpowernode/di05/applicationContext.xml";
		ApplicationContext ac = new ClassPathXmlApplicationContext(resource);

		Some some = (Some) ac.getBean("mySome");
		
		System.out.println(some);
		
	}

输出结果
Some [schools=[School [name=清华大学], School [name=北京大学]], myStrs=[中国, 北京], myList=[大兴, 亦庄], mySet=[大族企业湾, 10号楼], myMap={mobile=1234567, QQ=7654321}, myPros={education=大学, gender=男}]

集合属性注入简单写法

03di package com.bjpowernode.di06;
注意只有不使用ref的非引用数组和set集合才可以简写

只修改配置文件

<!-- 注册School  -->
    <bean id="mySchool" class="com.bjpowernode.di06.School">
    <property name="name" value="清华大学"/>

	</bean>
	
    <bean id="mySchool2" class="com.bjpowernode.di06.School">
    <property name="name" value="北京大学"/>

	</bean>
	
    <!-- 注册Some  -->
    <bean id="mySome" class="com.bjpowernode.di06.Some">
    <property name="schools">
    	<array>
    		<ref bean="mySchool"/>
    		<ref bean="mySchool2"/>  	
    	</array>

    </property>
	
	<property name="myStrs" value="中国,北京"/>

	<property name="myList" value="大兴,亦庄"/>
	
	<property name="mySet" value="大族企业湾,10号楼"/>
	
	<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>

对于域属性的自动注入

03di package com.bjpowernode.di07;
byName

autowire="byName"会从容器中查找与实体类的域属性同名的Bean的id,并将该Bean对象自动注入该该域属性

package07
配置文件

<!-- 注册School  -->
    <bean id="school" class="com.bjpowernode.di07.School">
    <property name="name" value="清华大学"/>

	</bean>
	
    <!-- 注册Student  -->
    <bean id="myStudent" class="com.bjpowernode.di07.Student" autowire="byName">
    <property name="name" value="张三"/>
    <property name="age" value="23"/>

byType

autowire=“byType” 会从容器中查找与实体类的域属性类型相同的(包括is-a继承关系的)Bean,并将该Bean对象自动注入给该域属性,也就是说域属性的id可以改为任意,也可以不写
注意类型相同的Bean如果有两个 会报错

03di package com.bjpowernode.di08;
继承自school类

public class PrimarySchool extends School {
	private String address;

	public void setAddress(String address) {
		this.address = address;
	}

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

配置文件

   <!-- 注册School  -->
    <bean id="mySchool" class="com.bjpowernode.di08.School">
    <property name="name" value="清华大学"/>

	</bean>
	
    <bean id="myPrimarySchool" class="com.bjpowernode.di08.School">
    <property name="address" value="海淀区"/>

	</bean>
	
    <!-- 注册Student  -->
    <bean id="myStudent" class="com.bjpowernode.di08.Student" autowire="byType">
    <property name="name" value="张三"/>
    <property name="age" value="23"/>
	
	</bean>

应修改为:去掉id="myPrimarySchool"这段代码

使用 SPEL

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

通过使用 SPEL 实现生成随机年龄,实现两个类的属性保持一致,实现调用另一个类的方法

总结:功能强大,可以调用静态方法,访问其他Bean的属性,计算表达式,调用其他Bean的方法

03di package com.bjpowernode.di09;
学生类

public class Student {
	private String name;
	private int age;
	
	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 + "]";
	}

	

}

人类

public class Person {
	private String pname;
	private int page;
	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;
	}
	@Override
	public String toString() {
		return "Person [pname=" + pname + ", page=" + page + "]";
	}
	
	public int computeAge() {
		return page > 25 ? 25 :page;
	}
	
}

配置文件

 <!-- 注册School  -->
    <bean id="myPerson" class="com.bjpowernode.di09.Person">
    <property name="pname" value="李四"/>
    <property name="page" value="#{T(java.lang.Math).random() * 50}"/>

	</bean>
	
    <!-- 注册Student  -->
    <bean id="myStudent" class="com.bjpowernode.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>

测试

@Test
	public void test01() {
		
		//创建容器对象,加载Spring配置文件
		//会从类路径src下查找配置文件
		//底层反射调用的是无参构造器new instance 如果写有参构造会屏蔽掉无参构造 导致初始化失败
		
		String resource = "com/bjpowernode/di09/applicationContext.xml";
		ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
		
		Person myPerson = (Person) ac.getBean("myPerson");
		System.out.println(myPerson);
		
		Student student = (Student) ac.getBean("myStudent");
		
		System.out.println(student);
		
	}

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

(一)平等关系 经常用
三种方式:
1)分别定义两个resource路径,传入两个参数
2)定义一个数组接收两个路径
3)最常用的使用通配符*
03-package com.bjpowernode.di13;
设置配置文件spring-base

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

设置配置文件spring-beans

<bean id="myStudent" class="com.bjpowernode.di13.Student" parent="baseBean">
    <property name="name" value="张三"/>
    <property name="age" value="23"/>
	</bean>
	
   <bean id="myTeacher" class="com.bjpowernode.di13.Teacher" parent="baseBean">
    <property name="name" value="Reyco"/>
    <property name="workAge" value="18"/>

	</bean>

测试三种写法

@Test
	public void test01() {
		//使用异类抽象Bean注入
		
		//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/bjpowernode/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);
	}

(二)包含关系
再写一个配置文件springtotal 引入那两个spring配置文件即可
即可分别引入,也可以使用通配符引用
03-package com.bjpowernode.di14;

     <!--  
	<import resource="classpath:com/bjpowernode/di14/spring-base.xml"/>
	<import resource="classpath:com/bjpowernode/di14/spring-beans.xml"/>
	-->
	
	<import resource="classpath:com/bjpowernode/di14/spring-*.xml"/>

在测试类中,直接使用springtotal即可

2.4 基于注解的 DI

对于 DI 使用注解,将不再需要在 Spring 配置文件中声明 Bean 实例。Spring 中使用注解,
需要在原有 Spring 运行环境基础上再做一些改变,完成以下三个步骤。

(1)导入 AOP 的 Jar 包。因为注解的后台实现用到了 AOP 编程。
(2)更换新的约束文件
%SPRING_HOME%\docs\spring-framework-reference\html\xsd-configuration.html
(3)需要在 Spring 配置文件中配置组件扫描器,用于在指定的基本包中扫描注解。
学校类 加入组件
04 package com.bjpowernode.di01;

@Component("mySchool") //  组件,表示当前类被Spring容器所管理 只写一个参数value可以省略
public class School {
	@Value("清华大学")
	private String name;

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

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

学生类 加入组件


@Component("myStudent") //  组件,表示当前类被Spring容器所管理
public class Student {
	@Value("张三")
	private String name;
	@Value("23")
	private int age;
	private 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 + "]";
	}

	

}

约束文件
扫描com.bjpowernode这个包及其子包
<context:component-scan base-package=“com.bjpowernode”/>
扫描com.bjpowernode这个包的子包
<context:component-scan base-package=“com.bjpowernode.*”/>
扫面一个包
<context:component-scan base-package=“com.bjpowernode.di01”/>

按类型与按名称注入域属性@Autowired 与@Qualifier

按类型
需要在域属性上使用注解@Autowired,该注解默认使用按类型自动装配 Bean 的方式。
使用该注解完成属性注入时,类中无需 setter。当然,若属性有 setter,则也可将其加
到 setter 上
04 package com.bjpowernode.di02;
学校类
在这里插入图片描述
学生类的域属性赋值
在这里插入图片描述
按名称
需要在域属性上联合使用注解@Autowired 与@Qualifier。@Qualifier 的 value 属性用于
指定要匹配的 Bean 的 id 值。同样类中无需 setter,也可加到 setter 上。
在这里插入图片描述
二者必须联合使用

域属性注解@Resource

和@Autowired用法一样

注解与 XML共同使用

注解的好处是,配置方便,直观。但其弊端也显而易见:以硬编码的方式写入到了 Java
代码中,其修改是需要重新编译代码的。
XML 配置方式的最大好处是,对其所做修改,无需编译代码,只需重启服务器即可将新
的配置加载。
若注解与 XML 同用,XML 的优先级要高于注解。这样做的好处是,需要对某个 Bean 做
修改,只需修改配置文件即可。当然,此时,Bean 类要有 setter 或构造器。

xml必须要有setter方法

04-package com.bjpowernode.di07;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值