spring创建对象的生命周期
spring作为一个IOC容器,主要作用是进行对象的创建和在容器中进行对象的管理,spring创建对象的时候,主要试用了工厂设计模式,并且对象创建过程是会经过一系列的处理。在spring创建对象和销毁的过程中,主要涉及的spring中的接口有:
- InitializingBean
- DisposableBean
- BeanPostProcessor bean后置处理器
另外,在spring创建对象后,会涉及对象中属性值的注入,注入过程中会涉及类型的转换,主要涉及的接口为: - Converter
我们来看一下前三个接口的作用以及整个spring创建对象的过程:
- InitializingBean接口:此接口作用是在对象属性注入完成后,调用其afterPropertiesSet方法,实现一些相关的初始化工作
- DisposableBean接口:此接口作用是在IOC容器销毁时进行调用,完成一些善后的工作
- BeanPostProcessor接口,此接口中有两个方法:postProcessBeforeInitialization和postProcessAfterInitialization,其中第一个方法时在对象初始化之前进行调用,第二个方法在对象初始化完成后进行调用
我们试用代码来看一下整体的创建和初始化过程:
@Data
public class Person implements InitializingBean, DisposableBean {
private String name ;
private Date birth ;
public void setName(String name){
this.name = name ;
System.out.println("Person.setName");
}
@Override
public void destroy() throws Exception {
System.out.println("Person.destroy");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Person.afterPropertiesSet");
}
}
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization: " + bean.getClass().getName());
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor.postProcessAfterInitialization: " + bean.getClass().getName());
return bean;
}
}
<!-- Person对象的声明 -->
<bean id="person" class="com.huwc.bean.Person">
<property name="name" value="huwenchao"></property>
<property name="birth" value="1986/06/26"></property>
</bean>
<!-- bean后置处理器的注册-->
<bean class="com.huwc.processor.MyBeanPostProcessor"></bean>
测试代码:
@Test
public void test1(){
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
Person p = (Person) ctx.getBean("person");
System.out.println("p = " + p);
ctx.close();
}
打印结果:
Person.setName
MyBeanPostProcessor.postProcessBeforeInitialization: com.huwc.bean.Person
Person.afterPropertiesSet
MyBeanPostProcessor.postProcessAfterInitialization: com.huwc.bean.Person
p = Person(name=huwenchao, birth=Thu Jun 26 00:00:00 CDT 1986)
Person.destroy
从以上的打印结果中我们可以看到整体的对象创建过程,如下:
- 调用person对象的set方法,进行属性值的注入
- 调用bean后置处理器的postProcessBeforeInitialization方法,进行对象初始化之前的拦截
- 调用InitializingBean接口的afterPropertiesSet方法,进行对象的初始化工作
- 调用bean后置处理器的postProcessAfterInitialization方法,进行对象初始化之后的拦截
- 调用DisposableBean的destroy,进行善后处理工作
以上,就是spring中创建对象并初始化的一系列过程。
Converter接口,主要时在对象进行属性值的注入时,进行类型的转换处理,我们也来看一下这个接口的作用:
对象在进行属性值的注入时,我们以Date类型来进行举例,在上面的代码执行中,我们可以看到:Person中有一个birth属性,是Date类型,并且我们没有配置相应的Converter,然而属性值却正常注入了,这是因为Spring中有一个默认的Date类型转换器,其实现了和String的“yyyy/mm/dd" 的转换,如果我们不想采用这种日期格式,那么就需要我们自己来实现相应的Converter了:
代码:
@Data
public class MyDateConverter implements Converter<String, Date> {
private String pattern ;
public Date convert(String source) {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
Date ret = null ;
try {
ret = sdf.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return ret;
}
}
<bean id="myDateConverter" class="MyDateConverter">
<property name="pattern" value="yyyy-mm-dd"></property>
</bean>
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<ref bean="myDateConverter"></ref>
</set>
</property>
</bean>
<bean id="person" class="com.huwc.bean.Person">
<property name="name" value="huwenchao"></property>
<property name="birth" value="1986-06-26"></property>
</bean>
测试结果:
p = Person(name=huwenchao, birth=Sun Jan 26 00:06:00 CST 1986)
以上,可以看到,我们在属性设置中,采用了”yyyy-mm-dd"的格式,并且通过自定义的Converter实现了类型的转换,成功进行了注入。
注意:在xml中注册converterService的时候,bean的id,必须指定为“conversionService”,如果设置为别的名称,则会报错。