Spring学习第二弹。
Spring-2-入门补充
基于XML的IOC的细节
1. Spring中工厂的类结构图
1. BeanFactory和ApplicationContext的区别
BeanFactory才是Spring容器中的顶层接口。
ApplicationContext是它的子接口
创建对象的时间点不一样(区别)
- ApplicationContext:一读取配置文件,默认就会创建对象。有点像立即加载(使用应用在单列设计模式)。
- BeanFactory:什么时候使用,什么时候加载。有点像延迟加载(适合多例场景)。
2. ApplicationContext接口的3个实现类
spring中ApplicationContext接口有三个实现类用于3种方式加载配置。
类根目录
ClassPathXmlApplicationContext
资源文件存放在res下。
磁盘任意目录
FileSystemXMLApplicationContext
资源配置文件存放在磁盘的其他地方。
注解
AnnotationConfigApplicationContext
1 | // 方式1 |
2. IOC中bean标签和管理对象细节
1. bean标签
作用:
- 用于配置对象来让spring来创建
- 默认情况下调用无参构造,如果没有参数则不能创建成功。
属性:
- id:给在容器中的对象指定唯一标识
- class:指定类的全限定类名。用来反射创建对象。默认调用无参数构造方法
- init-method:指定类中初始化方法名称
- destroy-method:指定类中销毁方法名称
- scope:指定对象作用的范围
- singleton:单例(默认)
- prototype:多例
- request:WEB项目中,Spring创建的Bean将其存入request域中
- session:WEB项目中,Spring创建的Bean将其存入session域中
- global session:WEB项目中,如果有多集群(多台服务器)的情况下,将其存入global session中
2. bean的作用范围和生命周期
单例:scope=“singleton”
一个应用只有一个对象的实例。作用范围:整个引用
生命周期:
- 出生:应用加载,创建容器时,对象被创建。
- 活着:容器存在,就一直活着。
- 销毁:应用卸载,容器销毁,对象被销毁。
多例:scope=”prototype”
每次访问对象,都会重新创建对象实例
生命周期
- 出生:当使用对象时,创建新的对象实例。
- 活着:对象被使用,一直活着。
- 死亡:长时间没有,java垃圾回收机制回收
3. 实例化Bean的三种方式
- 无参构造
- 静态工厂
- 实例工厂
使用无参构造(默认)
1
2
3
4
5
6public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImpl();
public void save() {
userDao.save();
}
}1
<bean id="userService" class="top.tobing.service.impl.UserServiceImpl"></bean>
使用静态工厂生产对象
1
2
3
4
5public class StaticFactory {
public static UserServiceImpl createUserService(){
return new UserServiceImpl();
}
}1
2<!--静态工厂生产对象-->
<bean id="staticUserService" class="top.tobing.factory.StaticFactory" factory-method="createUserService"></bean>使用实例工厂生产对象
1
2
3
4
5public class InstanceFactory {
public UserServiceImpl createUserService(){
return new UserServiceImpl();
}
}1
2
3<!--实例工厂生产对象-->
<bean id="instanceUserService" class="top.tobing.factory.InstanceFactory"></bean>
<bean id="userServiceI" factory-bean="instanceUserService" factory-method="createUserService"></bean>
3. Spring的依赖注入
依赖注入,Dependency Injection(简称DJ)。它是spring框架核心ioc的具体实现。
在编写程序时。我们通过Ioc(控制反转)把对象创建的控制权交给了spring。
代码中不可能完全没有依赖,IOC解耦只是降低他们的依赖关系,不可能完全消除依赖关系,例如:业务层仍然需要调持久层。
在使用了spring之后,我们连通把这种依赖也交给了spring维护。
就是说,我们只需让框架把持久层对象传入业务层,而不是我们自己获取。
1. 构造函数注入
- 通过使用类中构造函数,给成员变量赋值。
- 赋值的过程是使用配置文件的方式(如xml),让spring帮我们注入。
- constructor-arg标签
重写UserServiceImpl类用于演示依赖注入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public class UserServiceImpl implements UserService {
private String name;
private Integer age;
private Date birthday;
public UserServiceImpl(String name, Integer age, Date birthday) {
this.name = name;
this.age = age;
this.birthday = birthday;
}
public void save() {
System.out.println("Save method!"+name+","+age+","+birthday);
}
}编写bean.xml,给上述service层的对象传值。
1
2
3
4
5
6<bean id="userService" class="top.tobing.service.impl.UserServiceImpl">
<constructor-arg name="name" value="张三"></constructor-arg>
<constructor-arg name="age" value="19"></constructor-arg>
<constructor-arg name="birthday" ref="bir"></constructor-arg>
</bean>
<bean id="bir" class="java.util.Date"></bean>通过调用service层UserServiceImpl的save方法看是否注入成功
1
2
3
4
5
6
7
8public class UserUI {
public static void main(String[] args) {
// 1. 使用ApplicationContext接口(获取spring容器)
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
UserService userService = (UserService) ac.getBean("userService");
userService.save();
}
}结果:Save method!张三,19,Wed Dec 11 17:31:25 CST 2019
依赖注入对应关系
构造函数依赖注入涉及标签
- constructor-arg属性:
- ——————————-给谁赋值———————————–
- index:指定参数在构造函数参数列表的索引位置
- type:指定参数在构造函数中的数据类型
- name:指定参数在构造函数中的名称(实际中最常用)
- ——————————-赋什么赋值——————————–
- value:基本数据类型和String
- ref:赋值可以是其他bean,也就是说在配置文件中的其他bean
1
2
3
4
5
6
7
8
9
10
11
12<beans>
<bean id="userService" class="top.tobing.service.impl.UserServiceImpl">
<!--给参数列表中,属性名为name的赋值-->
<constructor-arg name="name" value="张三"></constructor-arg>
<!--给参数列表中,数据类型为Integer的参数赋值-->
<constructor-arg type="java.lang.Integer" value="19"></constructor-arg>
<!--给参数类表中,索引为2,(即第3个参数)赋值-->
<!--ref用于引用id为bir的另外一个bean-->
<constructor-arg index="2" ref="bir"></constructor-arg>
</bean>
<bean id="bir" class="java.util.Date" ></bean>
</beans>
2. set方法注入
通过类中setter方法注入
property标签
重写UserServiceImpl
1
2
3
4
5
6
7
8
9
10
11
12public class UserServiceImpl implements UserService {
private String name;
private Integer age;
private Date birthday;
public void setName(String name) {
this.name = name;
}
// 省略其余setter
public void save() {
System.out.println("Save method!"+name+","+age+","+birthday);
}
}编写配置文件建议对应关系,注入
1
2
3
4
5
6
7
8<beans>
<bean id="userService" class="top.tobing.service.impl.UserServiceImpl">
<property name="age" value="20"></property>
<property name="name" value="tobing"></property>
<property name="birthday" ref="bir"></property>
</bean>
<bean id="bir" class="java.util.Date" ></bean>
</beans>测试
1
2
3
4// 1. 使用ApplicationContext接口(获取spring容器)
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
// 2. 调用方法
UserService userService = (UserService) ac.getBean("userService");Save method!tobing,20,Wed Dec 11 18:27:46 CST 2019
3. p名称空间注入(本质调用setter方法)
通过在xml中导入p名称空间,使用p:注入属性名称=xxx来注入数据。
编写service层(和set方法一致)
编写配置文件
注意导入p空间: xmlns:p=”http://www.springframework.org/schema/p"
注意非基本数据类型和String要使用:属性名-ref 来注入。
1
2
3
4
5
6
7
8
9
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userService" class="top.tobing.service.impl.UserServiceImpl" p:age="18" p:name="Rongon" p:birthday-ref="bir"></bean>
<bean id="bir" class="java.util.Date" ></bean>
</beans>
4. 注入集合属性
通过setter,给集合成员(数组、List、Set、Map、Properties)传值。
给service层添加集合元素用于测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public class UserServiceImpl implements UserService {
private String[] myStrs;
private List<String> myList;
private Set<String> mySet;
private Map<String,String> myMap;
private Properties myPropers;
public void setMyStrs(String[] myStrs) {
this.myStrs = myStrs;
}
// setter
public void save() {
System.out.println(Arrays.toString(myStrs));
System.out.println(myList);
System.out.println(mySet);
System.out.println(myMap);
System.out.println(myPropers);
}
}
编写配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46<bean id="userService" class="top.tobing.service.impl.UserServiceImpl">
<!--字符数组-->
<property name="myStrs">
<set>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
<value>DDD</value>
</set>
</property>
<!--List-->
<property name="myList">
<list>
<value>List1</value>
<value>List2</value>
<value>List3</value>
<value>List4</value>
</list>
</property>
<!--Set-->
<property name="mySet">
<set>
<value>Set1</value>
<value>Set2</value>
<value>Set3</value>
<value>Set4</value>
</set>
</property>
<!--Properties-->
<property name="myPropers">
<props>
<prop key="testA">aaa</prop>
<prop key="testB">bbb</prop>
</props>
</property>
<!--Map-->
<property name="myMap">
<map>
<entry key="mapA" value="aaa"></entry>
<entry key="mapB" value="bbb"></entry>
<entry key="mapC">
<value>CCC</value>
</entry>
</map>
</property>
</bean>测试
1
2
3
4
5
6
7
8public class UserUI {
public static void main(String[] args) {
// 1. 使用ApplicationContext接口(获取spring容器)
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
UserService userService = (UserService) ac.getBean("userService");
userService.save();
}
}1
2
3
4
5[AAA, BBB, CCC, DDD]
[List1, List2, List3, List4]
[Set1, Set2, Set3, Set4]
{mapA=aaa, mapB=bbb, mapC=CCC}
{testB=bbb, testA=aaa}注意
在集合数据注入时,同一种集合元素可以共用一种标签,例如:
- List结构:
- array、list、set
- Map结构:
- map、entry、props、prop
- List结构: