SpringBean的生命周期
- SperingBean的生命周期是从Bean实例化之后,即通过反射创建出对象之后,到Bean成为一个完整对象,最终存储到单例池中,这个过程被称为Spring Bean的生命周期。Spring Bean的生命周期大体上分为三个阶段
- Bean的实例化阶段:Spring框架会取出BeanDefiniton的信息进行判断当前Bean的范围是否是singleton的,是否不是延迟加载的,是否不是FactoryBean等,最终将一个普通的singleton的Bean通过反射(加载类)进行实例化
- Bean的初始化阶段(着重研究):Bean创建之后还仅仅是个半成品,还需要对Bean实例的属性进行填充、执行一些Aware接口方法、执行BeanPostProcessor方法,执行InitializingBean接口的初始化方法、执行自定义初始化init方法等。该阶段是Spring最具有技术含量和复杂程度的阶段,AOP增强功能,后面学习的Spring的注解功能等、spring高频面试题Bean的循环引用问题都是在这个阶段体现的
- Bean的完成阶段:经过初始化阶段,Bean就成为了一个完整的Spring Bean,被存储到单例池singletonObjects中,即完成了Spring Bean的整个生命周期。
Spring Bean的初始化阶段涉及过程
- Bean实例属性的填充
- Aware接口属性的注入
- BeanPostProcessor的before()方法回调
- InitializingBean接口的初始化方法回调
- 自定义初始化方法init回调
- BeanPostProcessor的after()方法回调
Bean实例属性填充
-
BeanDefinition中对当前Bean实体的注入信息通过属性propertyValue进行了储存,例如UserService的属性信息如下
XML<bean id="userService" class="com.example.Service.Impl.UserServiceImpl"> <property name="userDAO" ref="userDAO"></property> <property name="name" value="hhhh"></property> </bean> <bean name="userDAO" class="com.example.DAO.Impl.UserDAOImpl"></bean>
属性注入的三种情况
-
注入普通属性,String,int或存储基本类型的集合时,直接通过set方法反射设置进去
- 上述属性name对应类中的set方法
-
注入单向对象引用属性时,从容器中getBean获取后通过set方法反射设置进去,如果容器中没有,则先创建被注入对象Bean实例(完成整个生命周期)后,再进行注入操作
- 上述UserDAO属性的注入
- 根据配置文件中bean的位置不同,进行的顺序也不一样
- 主要代码如下
- UserServiceImpl类
javapackage com.example.Service.Impl; import com.example.DAO.UserDAO; import com.example.Service.UserService; public class UserServiceImpl implements UserService { public UserServiceImpl() { System.out.println("UserService对象创建"); } private UserDAO userDAO; private String name; public void setName(String name) { this.name = name; } public void setUserDAO(UserDAO userDAO) { System.out.println("UserService执行注入UserDAO的操作:setDAO方法"); this.userDAO = userDAO; } @Override public void show() { System.out.println("show~~~"); } }
-
UserDAOImpl类
javapackage com.example.DAO.Impl; import com.example.DAO.UserDAO; public class UserDAOImpl implements UserDAO { public UserDAOImpl() { System.out.println("UserDAO对象创建"); } }
-
测试类
javapackage com.example.Test; import com.example.Service.UserService; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestApplicationContext { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml"); UserService UserServiceBean = (UserService) context.getBean(UserService.class); } }
-
若配置文件中先创建UserADO的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 class="com.example.PostProcessor.TimeLogBeanPostProcessor"></bean> <!-- <bean id="userService" class="com.example.Service.Impl.UserServiceImpl">--> <!-- </bean>--> <!-- <bean id="userDAO" class="com.example.DAO.Impl.UserDAOImpl">--> <!-- </bean>--> <!-- <alias name="userDAO" alias="xxx"/>--> <!-- <alias name="userDAO" alias="yyy"/>--> <bean name="userDAO" class="com.example.DAO.Impl.UserDAOImpl"></bean> <bean id="userService" class="com.example.Service.Impl.UserServiceImpl"> <property name="userDAO" ref="userDAO"></property> <property name="name" value="hhhh"></property> </bean> </beans>
-
测试类运行结果为
-
若配置文件中先创建UserService的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 class="com.example.PostProcessor.TimeLogBeanPostProcessor"></bean> <!-- <bean id="userService" class="com.example.Service.Impl.UserServiceImpl">--> <!-- </bean>--> <!-- <bean id="userDAO" class="com.example.DAO.Impl.UserDAOImpl">--> <!-- </bean>--> <!-- <alias name="userDAO" alias="xxx"/>--> <!-- <alias name="userDAO" alias="yyy"/>--> <bean id="userService" class="com.example.Service.Impl.UserServiceImpl"> <property name="userDAO" ref="userDAO"></property> <property name="name" value="hhhh"></property> </bean> <bean name="userDAO" class="com.example.DAO.Impl.UserDAOImpl"></bean> </beans>
-
运行结果如下
-
注入双向对象引用属性时,就比较复杂了,涉及循环引用(循环依赖)问题,下面会详细阐释解决方案。(明天再来,女朋友来了,不能学习了p51)