概述:
对于Spring框架中的Bean对象的生命周期,从大体上基本可分为以下几个阶段:
1.实例化阶段:
实例化即指的是IOC容器通过反射机制创建bean对象的过程(默认使用单例模式)。此过程又可被分为以下几个阶段:
(1)加载通过xml配置文件或注解注入IOC容器内所有的类,并通过BeanDefinitionReader接口中的方法将注入容器中的类对应生成BeanDefinition对象。BeanDefinition对象包含了此类的所有信息。
(2)将所有生成的BeanDefinition对象(下面称为db对象)一一存入一个叫beanDefinitionMap的集合中。
(3)遍历此集合,取出所有的db对象,执行Bean工厂的后处理器,通过BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor两个接口的实现类的方法实现db对象类型的修改或注册新的db对象。如下图所示:
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory)
throws BeansException {
System.out.println("MyBeanFactoryPostProcessor的postProcessBeanFactory方法");
//修改
BeanDefinition beanDefinition=configurableListableBeanFactory.getBeanDefinition("stu");
beanDefinition.setBeanClassName("com.ape.bean.User");
//新增
BeanDefinition beanDefinitions=new RootBeanDefinition();
beanDefinition.setBeanClassName("com.ape.bean.User");
DefaultListableBeanFactory defaultListableBeanFactory=(DefaultListableBeanFactory)
configurableListableBeanFactory;
defaultListableBeanFactory.registerBeanDefinition("user" ,beanDefinition);
}
}
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry)
throws BeansException {
//修改
BeanDefinition beanDefinition=beanDefinitionRegistry.getBeanDefinition("stu");
beanDefinition.setBeanClassName("com.ape.bean.User");
//新增
BeanDefinition beanDefinitions=new RootBeanDefinition();
beanDefinition.setBeanClassName("com.ape.bean.User");
beanDefinitionRegistry.registerBeanDefinition("user" ,beanDefinition);
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory)
throws BeansException {
}
}
(4)通过反射机制调用注入容器类的无参构造真正创建出bean对象,但此时创建出的bean对象还不完整,暂存于三级缓存singletonFactories中(如存在循环依赖则根据引用关系将被引用者存于二级缓存earlySingletonObjects中)。此时即完成了bean对象的实例化阶段。
2.初始化阶段:
在bean对象的初始化阶段主要又可分为以下几个阶段:
(1)属性赋值阶段:此阶段主要通过注入IOC容器中类的set方法或构造方法完成bean对象的属性赋值(通过XML配置文件和注解的方式写法有所不同)。在xml配置文件中主要通过bean标签中的property子标签实现set注入,通过constructor-arg子标签实现构造方法注入,如下图所示:
<!--基本类型和String-->
<bean id="student" class="com.ape.bean.Student">
<property name="name" value="张三"></property>
<property name="age" value="18"></property>
</bean>
<!--javaBean类型-->
<bean id="iuserdao" class="com.ape.dao.UserDaoImpl"></bean>
<bean id="iservice" class="com.ape.service.ServiceImpl">
<property name="iUserDao" ref="iuserdao"></property>
</bean>
<bean id="icotroller" class="com.ape.cotroller.CotrollerImpl">
<property name="service" ref="iservice"></property>
</bean>
<!--复杂类型(集合,数组)-->
<bean id="teacher" class="com.ape.bean.Teacher">
<property name="set">
<set>
<value>张三</value>
<value>李四</value>
<value>王五</value>
</set>
</property>
<property name="list">
<list>
<value>英雄联盟</value>
<value>穿越火线</value>
<value>DNF</value>
</list>
</property>
<property name="arr">
<array>
<value>亚索</value>
<value>亚托克斯</value>
<value>菲奥娜</value>
</array>
</property>
<property name="map">
<map>
<entry key="放逐之刃" value="锐雯"></entry>
<entry key="刀锋之影" value="泰隆"></entry>
<entry key="影流之主" value="劫"></entry>
</map>
</property>
<property name="pro">
<props>
<prop key="刀锋意志">艾瑞利亚</prop>
<prop key="铁铠冥魂">莫德凯撒</prop>
<prop key="复仇之矛">卡莉斯塔</prop>
</props>
</property>
</bean>
<!--基本类型和String-->
<bean id="student" class="com.ape.bean.Student">
<constructor-arg name="name" value="张三"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
</bean>
<!--javabean类型-->
<bean id="iuserdao" class="com.ape.dao.UserDaoImpl"></bean>
<bean id="iservice" class="com.ape.service.ServiceImpl">
<constructor-arg name="iUserDao" ref="iuserdao"></constructor-arg>
</bean>
<bean id="icotroller" class="com.ape.cotroller.CotrollerImpl">
<constructor-arg name="service" ref="iservice"></constructor-arg>
</bean>
<!--构造方法方式不支持复杂类型-->
对于注解的写法,主要则通过@value实现基本类型的属性赋值,通过@Autowired或@Qualifier和@Resource注解完成复杂类型的装配。如下图所示:
@Component(value = "stu")
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
public class Student {
// @Value("张三")
@Value("${mess1}")
private String sname;
// @Value("18")
@Value("${mess2}")
private int age;
@Service
public class ServiceImpl implements IService{
// @Autowired
// @Qualifier(value = "userDaoImpl")
//@Resource(name="userDaoImpl")
@Autowired
IUserDao userDaoImpl02;
public void save() {
System.out.println("service的save方法");
userDaoImpl02.save();
}
}
(2)实现Aware接口:如果注入IOC容器的类实现了某个或多个Aware接口,则会根据实现的接口的回调方法完成一些相关的操作。如下图所示:
public class User implements BeanFactoryAware, BeanNameAware, ApplicationContextAware {
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println(beanFactory);
}
public void setBeanName(String s) {
System.out.println(s);
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println(applicationContext);
}
}
以下是几个常用Aware接口的方法详解:
(3)执行bean的后处理中的Before方法:如果存在BeanPostProcessor接口的实现类,则在执行完Aware接口的方法后执行BeanPostProcessor接口中的Before方法,完成相关操作。如下图所示:
public class MyProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyProcessor的before方法");
return bean;
}
(4)执行bean对象的初始化操作:如果注入IOC容器的类实现了InitializingBean接口,则会执行重写此接口的方法(接口初始化),完成相关操作,如果自定义了初始化方法(属性初始化),则会执行自定义的初始化方法。注意属性初始化方法需要与Spring框架绑定,执行时先执行接口初始化,后执行属性初始化。如下所示:
public class Student implements InitializingBean {
private String name;
public Student() {
System.out.println("学生类创建");
}
public void setName(String name) {
System.out.println("属性填充");
this.name = name;
}
public void afterPropertiesSet() throws Exception {
System.out.println("接口初始化");
}
public void doit(){
System.out.println("属性初始化");
}
}
(5)执行bean的后处理中的After方法:如果存在BeanPostProcessor接口的实现类,在执行完初始化的相关方法后执行BeanPostProcessor接口中的After方法,如下所示:
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("MyProcessor的after方法");
return bean;
}
(6)执行完以上操作后就已经基本上完成了bean对象的整个初始化阶段。此时所有注入IOC容器的类的bean对象均已创建完成,并存入一级缓存singletonObjects中,供调用者获取。
3.操作使用阶段:
在bean对象完成实例化和初始化并存入一级缓存后,即可通过Application接口的getBean()获取需要的bean对象进行操作使用了。
4.销毁阶段:
bean对象的销毁主要有两种方式:
(1)通过实现DisposableBean接口实现接口销毁。
(2)通过自定义销毁方法实现属性销毁(自定义方法需绑定Spring框架)
(3)如果两个方法都有,则先执行接口销毁,再执行属性销毁。
如下所示:
public class Teacher implements InitializingBean , DisposableBean {
private String tname;
public Teacher() {
System.out.println("javaBean的实例化");
}
public void setTname(String tname) {
System.out.println("属性复制");
this.tname = tname;
}
public void afterPropertiesSet() throws Exception {
System.out.println("接口初始化");
}
public void doinit(){
System.out.println("属性初始化");
}
public void destroy() throws Exception {
System.out.println("接口销毁");
}
public void dodestory(){
System.out.println("属性销毁");
}
}
总结:
bean对象的整个创建过程如下图所示:
注意事项:bean的生命周期只针对于通过单例模式创建出来的bean对象,对于多例模式创建的bean对象而言,生命周期这个概念是没有意义的。