# Spring基于XML的IOC细节
## 一、Spring中的工厂的类结构图
---
@@@@@@@@@@@@@@@@@@@@@@@@@@2 spring中工厂的类结构图.png
---
@@@@@@@@@@@@@@@@@@@@@@@@@@2 spring中工厂的类结构图关系.png
### 1. BeanFactory和ApplicationContext的区别
1. **`BeanFactory`** 是Spring容器的顶层接口。
- 需要使用时创建对象
2. **`ApplicationContext`** 是`BeanFactory`的子接口
- 只要一读取配置文件,默认情况下就会创建对象。
### 2. ApplicationContext接口的实现类
1. **`ClassPathXmlApplicationContext`**
- 【推荐!】从根路径下加载配置文件
2. **`FileSystemXmlApplicationContext`**
- 【忘记吧!】从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。
3. **`AnnotationConfigApplicationContext`**
- 当使用注解配置容器对象时,需要使用此类来创建spring容器。它用来读取注解。
## 二、IOC中bean标签和管理对象细节
> bean.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 标签:用于配置让spring 创建对象,并且存入ioc容器中
id 属性:对象的唯一标识
class 属性:指定要闯将对象的全限定类名
-->
<!-- 配置service -->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
<bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl" ></bean>
</beans>
```
### 1. bean标签的作用
1. 用于配置对象让spring来创建。
2. 【默认情况下】调用的是类中的无参构造函数【反射】。如果没有无参构造函数则不能创建成功。
### 2. bean标签的属性介绍
```
<bean
id="accountDao"
-- 给对象在容器中提供一个唯一标识。用于获取对象。
class="com.itheima.dao.impl.AccountDaoImpl"
-- 指定类的全限定类名。用于反射创建对象。默认情况下调用无参构造函数
scope="prototype"
-- 指定对象的作用范围:取值及其含义如下
-- singleton: 默认值,单例的
-- prototype: 多例的
-- request: web项目中,Spring创建一个Bean对象,将对象存入request域中
-- session: web项目中,Spring创建一个Bean对象,将对象存入session域中
-- golbal session: web项目中,【应用在Protlet环境】,如果没有Protlet
环境,那么golbalSession相当于session
init-method="init"
-- 指定类中的初始化方法的名称
destroy-method="destory"
-- 指定类中销毁方法的名称
></bean>
```
### 3. bean的作用范围和生命周期
#### 1. 单例对象:属性scope="singleton"
> 一个应用只有一个对象的实例。作用范围就是整个引用
- **生命周期**:
- 对象出生:当应用加载,创建容器市,对象就被创建了。
- 对象活着:容器在,对象在
- 对象拜拜:应用卸载、容器销毁时。
#### 2. 多例对象:属性scope="prototype"
> 每次访问对象时,都会重新创建对象实例
- **生命周期**:
- 对象出生:当使用对象时
- 对象活着:对象在被使用中
- 对象拜拜:长时间不使用,被java的垃圾回收机制GC回收了
#### 3. 实例化Bean的三种方式
##### 1. 使用默认无参构造函数
> 在默认情况下:会根据默认无参构造函数来创建类对象,如果没有默认无参构造函数,将会创建失败。
```
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"/>
```
##### 2. spring管理【静态】工厂-使用静态工厂的方式创建对象
> 比如,如下:使用StaticFactory类中静态方法createAccountService创建对象,并存入spring容器
1. 模拟一个**静态**工厂类,创建业务层实现类
```
public class StaticFactory {
public static AccountService createAccountService() {
return new AccountServiceImpl();
}
}
```
2. 配置文件bean.xml
```
<bean
id="accountService"
-- 指定bean的id,用于从容器中获取
class="com.itheima.factory.StaticFactory"
-- 指定【静态工厂】的全限定类名
factory-method="createAccountService"
-- 指定生产对象的静态方法
></bean>
```
##### 3. spring管理【实例】工厂-使用实力工厂的方法创建对象
> 先把工厂的创建交给spring来管理,然后再使用工厂的bean来调用里面的方法;
*演示:模拟一个实例工厂,创建业务层实现类,此工厂创建对象,必须现让spring创建该工厂的实例对象,再调用方法*
1. **实例**工厂类
```
public class InstanceFactory {
public AccountService createAccountService() {
return new AccountServiceImpl();
}
}
```
2. bean.xml配置
```
<bean id="instancFactory" class="com.itheima.factory.InstanceFactory"></bean>
-- 实例工厂的bean配置
<bean id="accountService"
factory-bean="instancFactory"
-- 指定实例工厂bean的id
factory-method="createAccountService"
-- 指定实例工厂中创建对象的方法
></bean>
```
## 三、Spring的依赖注入
> 依赖注入:Dependency Injection,spring框架核心ioc的具体实现。程序在编写时,通过控制反转,把对象的创建交给了 spring,但是代码中不可能出现没有依赖的情况。ioc 解耦只是降低他们的依赖关系,但不会消除。例如:我们的业务层仍会调用持久层的方法。那这种业务层和持久层的依赖关系,在使用 spring 之后,就让 spring 来维护了。简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。
### 1. 构造函数注入
> 顾名思义,就是使用类中的构造函数,给成员变量赋值。注意,赋值的操作不是我们自己做,而是通过配置的方式,让spring框架来为我们注入。
1. 被注入的类案例:【类中需要提供一个对应参数列表的构造函数】
```
public class AccountServiceImpl implements AccountService {
private String name;
private Integer age;
private Date birthday;
public AccountServiceImpl(String name, Integer age, Date birthday) {
this.name = name;
this.age = age;
this.birthday = birthday;
}
...
```
2. bean.xml对应的配置的标签`constructor-arg`介绍
```
<constructor-arg
index="1"
-- 指定参数在构造函数参数列表的索引位置
type="Integer"
-- 指定参数在构造函数中的数据类型
name="name"
-- 指定参数在构造函数中的名称
-\-\ 上面三个是找给谁赋值,下面两个是赋什么值 /-/-
value="张三"
-- 它能赋的值是基本的数据类型和String类型
ref="now"
-- 能赋的值为其他的bean类型,在配置文件中得配置该bean标签,如下
></constructor-arg>
<bean id="now" class="java.util.Date"></bean>
```
3. bean.xml配置案例
```
<bean id="now" class="java.util.Date"></bean>
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<constructor-arg name="name" value=" 张三 "></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>
```
### 2. set方法注入【开发中的常客】
> 需要在类中提供set方法
1. bean类文件案例
```
public class AccountServiceImpl implements IAccountService {
private String name;
private Integer age;
private Date birthday;
public void setName(String name) { this.name = name; }
public void setAge(Integer age) { this.age = age; }
public void setBirthday(Date birthday) { this.birthday = birthday; }
...
```
2. 涉及的标签`property`
```
<property
name="name"
-- 被注入类的对应set方法“set”之后的部分首字母小写!
value="test"
-- 给属性赋值为基本数据类型和string类型的
ref="now"
-- 给属性赋值是其他bean类型的
></property>
<bean id="now" class="java.util.Date"></bean>
```
3. bean.xml配置案例
```
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<property name="name" value="test"></property>
<property name="age" value="21"></property>
<property name="birthday" ref="now"></property>
</bean>
<bean id="now" class="java.util.Date"></bean>
```
### 3. 使用p名称空间注入数据(本质还是调用set方法)【了解】
> 此种方式通过xml中导入p名称空间,使用`p:propertyName`来注入数据,本质还是调用set方法实现注入功能
1. java代码【->2. set方法注入【开发中的常客】->1. bean类文件案例】
2. 配置文件案例
```
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
-- 引入此命名空间约束
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="accountService"
class="com.itheima.service.impl.AccountServiceImpl4"
p:name="test" p:age="21" p:birthday-ref="now"/>
-- p:propertyName的形式
</beans>
```
### 4. 注入集合属性
> 给类中的集合成员传值,用的也是注入的方式,只不过变量的数据类型都是集合。一般注入的集合类型为List、Set、Map、Properties
1. 被注入的JavaBean
```
public class AccountServiceImpl implements AccountService {
private String[] myStrs;
private List<String> myList;
private Set<String> mySet;
private Map<String, String> myMap;
private Properties myProps;
public String[] getMyStrs() { return myStrs; }
public void setMyStrs(String[] myStrs) { this.myStrs = myStrs; }
public List<String> getMyList() { return myList; }
public void setMyList(List<String> myList) { this.myList = myList; }
public Set<String> getMySet() { return mySet; }
public void setMySet(Set<String> mySet) { this.mySet = mySet; }
public Map<String, String> getMyMap() { return myMap; }
public void setMyMap(Map<String, String> myMap) { this.myMap = myMap; }
public Properties getMyProps() { return myProps; }
public void setMyProps(Properties myProps) { this.myProps = myProps; }
...
```
2. bean.xml中对应的配置
- 注入集合数据时,只要结构相同,标签可以互换
- 注入集合时,根据类型选择标签,同种集合类型通用
- List结构:
- `<array></array>`
- `<list></list>`
- `<set></set>`
- Map结构的
- `<map></map>`
- `<entry></entry>`
- `<prop></prop>`
- `<props></props>`
```
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<!-- 给数组注入数据 -->
<property name="myStrs">
<set>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</set>
</property>
<!-- 注入list集合数据 -->
<property name="myList">
<list>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</list>
</property>
<!-- 注入set集合数据 -->
<property name="mySet">
<set>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</set>
</property>
<!-- 注入Map数据 -->
<property name="myMap">
<props>
<prop key="A">AAA</prop>
<prop key="B">BBB</prop>
</props>
</property>
<!-- 注入properties数据 -->
<property name="myProps">
<map>
<entry key="A" value="AAA"></entry>
<entry key="B">
<value>BBB</value>
</entry>
</map>
</property>
</bean>
```
## 四、Spring配置文件中提示的配置【Eclipse】
---
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ spring配置文件提示配置【Eclipse】.png
|
|