10.对象的生命周期
1. 什么是对象的生命周期
指的是对象创建、存活、消亡的一个完整过程
2. 为什么要学习对象的生命周期
由spring负责对象的创建、存活、销毁,了解生命周期,有利于使用好sprig创建我们的对象
3. 生命周期的三个阶段
- 创建阶段
也就是spring工厂何时创建对象
1. scope = "singleton"
spring工厂创建的同时,对象创建
注意:如果也想设置获取对象的同时创建对象,那么只需要添加 <bean lazy-init="true"/>
2. scope = "prototype"
spring会在获取对象的同时创建对象
ctx.getBean("")
- 初始化阶段
spring工厂在创建完成对象后,调用对象的初始化方法,完成对应的初始化操作
1. 初始化方法由谁提供:程序员根据需求,提供初始化方法,完成初始化操作
2. 初始化方法由谁调用:spring工厂调用
- InitializaingBean接口
//初始化方法,可以做一些初始化操作
public void afterProperitesSet(){}
- 对象中提供一个普通方法
public void MyInit(){}
<init-method="MyInit">
- 细节分析
(1)如果一个对象即实现了InitializaingBean接口,同时又提供了普通的初始化方法,会怎样?
1. InitializaingBean先执行
2. 普通的初始化方法
(2)注入发生在初始化
(3)什么叫做初始化操作
对资源的初始化(数据库、IO、网络...)
- 销毁阶段
spring销毁对象前,会调用对象的销毁方法,完成销毁操作
1. 什么时候会销毁所创建的对象?
ctx.close();
2. 销毁方法:程序员根据自己的需求,定义销毁的方法
由spring工厂完成调用
- DisposableBean
public void destroy() throws Exception {}
- 定义普通方法
public void MyDestroy(){}
<destroy-method="">
- 细节分析
1. 销毁方法只适用 scope="singleton"
2. 什么叫做销毁操作?
主要指的是:io.close() connect.close() ...
4. 对象生命周期总结
11.配置文件参数化
把spring配置文件中经常要修改的字符串信息,转移到一个小的配置文件中
1. 配置文件中存在经常要修改的字符串信息吗?
存在,以数据库连接相关的参数为代表
2. 经常变化的字符串,在spring配置文件中,直接修改,不利于项目维护(修改)
3. 转移到一个小的配置文件中(.properties),利于维护(修改)
配置文件参数化,有利于spring配置文件的维护
1. 配置文件参数化的开发步骤
- 提供一个小的配置文件(.properties)
名字: 随便
位置: 随便
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/stu?useSSL=false
jdbc.username=root
jdbc.password=123456
- spring配置文件和小配置文件整合
在applicationContext.xml中添加:
<context:property-placeholder location="classpath:/db.properties"/>
- 在spring配置文件中通过${}获取小配置文件中的值
12.自定义类型转换器
1.类型转换器
作用:spring通过类型转换器把配置文件中的字符串类型的数据,转化为对象中成员变量对应的数据,进而完成了注入
2.自定义类型转换器
产生原因:当spring内部没有提供特定的类型装换器时,而程序员在应用过程中还需要使用,那么就需要程序自定义类型转换器
- 类实现 Converter 接口
public class MyDateConverter implements Converter<String,Date> {
/**
* 作用:String --> Data
* SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd")
* sdf.parse(String) --> Data
*
* @param source 代表的就是配置文件中的<value>2022-1-1</value>
* @return 把转换好的Data作为方法的返回值,Spring自动的为 birthday 属性进行注入(赋值)
*/
@Override
public Date convert(String source) {
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd");
Date date = null;
try {
date = sdf.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
- 在Spring配置文件中进行配置
- MyDataConverter对象创建出来
<bean id="myDateConverter" class="xxx.MyDateConverter"/>
- 类型转换器的注册
目的: 告知Spring我们创建的MyDateConverter是一个类转换器
<!--Spring创建 MyDateConverter 类型的对象-->
<bean id="myDateConverter" class="com.xxc.converter.MyDateConverter"/>
<!--用于注册类型转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<!--
setConverters(Set<?> converters)
-->
<set><ref bean="myDateConverter"/> </set>
</property>
</bean>
- 细节
3.1 MyDateConverter中的日期格式,也通过配置文件,通过注入的方式进行赋值
public class MyDateConverter implements Converter<String,Date> {
private String pattern;
public String getPattern() {
return pattern;
}
public void setPattern(String pattern) {
this.pattern = pattern;
}
/**
* 作用:String --> Data
* SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd")
* sdf.parse(String) --> Data
*
* @param source 代表的就是配置文件中的<value>2022-1-1</value>
* @return 把转换好的Data作为方法的返回值,Spring自动的为 birthday 属性进行注入(赋值)
*/
@Override
public Date convert(String source) {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
Date date = null;
try {
date = sdf.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
<!--Spring创建 MyDateConverter 类型的对象-->
<bean id="myDateConverter" class="com.xxc.converter.MyDateConverter" >
<property name="pattern" value="yyyy-MM-dd"/>
</bean>
3.2 ConverterServiceFactoryBean 在定义id属性时,值必须为 converterService
3.3 Spring框架内置的日期转换器
日期格式:2022/01/01 (不支持2022-1-1)
13.后置处理Bean
BeanPostProcessor作用:对spring工厂创建的对象进行再加工
AOP底层实现
注意:BeanPostProcessor接口
程序员需要实现BeanPostProcessor接口规定的方法:
postProcessBeforeInitialization(Object bean,String beanName){}
作用:Spring在创建完对象并注入后,可以运行Before方法进行加工
获得spring创建好的对象:通过方法参数
最终通过返回值交给spring框架
postProcessAfterInitilization(Object bean,String beanName){}
作用:Spring在执行完对象的初始化后,可以运行After方法进行加工
获得spring创建好的对象:通过方法参数
最终通过返回值交给spring框架
实战中:
很少处理spring的初始化操作,就没有必要区分Before和After。只需要实现其中一个方法(After)即可
注意:
当只实现After时,那么Before方法需要返回bean
- BeanPostProcessor开发步骤
- 创建类实现BeanPostProcessor接口
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Categroy) {
Categroy categroy = (Categroy) bean;
categroy.setName("xiaoxiao");
return categroy;
}
return bean;
}
}
- spring配置文件中配置
<bean id="myBeanPostProcessor" class="com.xxc.beanpost.MyBeanPostProcessor"/>
- 细节
BeanPostProcessor会对Spring工厂创建的所有对象进行加工