SpringBean的生命周期
SpringBean的生命周期在Bean实例化之后,到Bean成为一个完整的对象,最终存储到单例池中,总体分为
- Bean的实例化过程:从BeanDefinition到Bean的过程
- Bean的初始化过程:创建完Bean后执行包括BeanPostProcessor、init方法等内容
- Bean的完成阶段:经过初始阶段就成为了一个完整的SpringBean,存储到单例池中
Spring初始化过程
- Bean实例的属性填充也就是各种set方法
- Aware接口属性注入
- BeanPostProcessor的before()方法回调
- InitializingBean接口的初始化方法回调afterPropertiesSet()
- 自定义初始化init回调
- BeanPostProcessor的after()方法回调
Bean属性填充
Bean实例的信息也会被BeanDefinition封装
- 当注入是普通属性的时候,直接通过set方法反射设置进去
- 注入单向对象引用,就比如说Service需要Dao的注入,可以反转下面两个bean对象的创建过程,通过输出来观察两者之间的差异。
<bean id="userService" class="com.itheima.service.impl.UserServiceimpl">
<property name="username" value="123123"/>
<!-- 将userDao传入到setUserDao方法中 注意这边使用的是ref标签 -->
<property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl" init-method="init"/>
-
双向注入,Dao和Service相互依赖需要注入,这个部分是比较重要的,一般在面试中都会进行提问。过程和单向注入差不多,但是要求能够了解其中的缓存机制。
<bean id="userService" class="com.itheima.service.impl.UserServiceimpl"> <property name="username" value="123123"/> <!-- 将userDao传入到setUserDao方法中 注意这边使用的是ref标签 --> <property name="userDao" ref="userDao"/> </bean> <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl" init-method="init"> <property name="userServiceimpl" ref="userService"/> </bean>
缓存机制
Spring提供三级缓存用于存储完整的Bean实例和半成品Bean实例
- 一级缓存:singletonObjects,完整的Bean成品
- 二级缓存:earlySingletonObject,半成品bean,但是已经被其他对象所引用
- 三级缓存:singletonFactories,半成品bean并且未被其他对象引用,每一个实例化Bean的创建一开始都会被存放在三级缓存中。
过程描述
- UserService实例化对象,但尚未进行初始化放到三级缓存。
- UserService因为缺少UserDao所以没办法直接完成实例对象的创建,所以就存放到三级缓存中
- UserDao开始创建,未初始化存放到三级缓存中。
- UserDao需要进行注入,在三级缓存中获取到了UserService,UserService将会因为被引用了所以从三级缓存转移到二级缓存中去。
- UserDao执行其他的生命周期过程,最终成为一个完整的Bean,存放在一级缓存中,删除二三级缓存。
- UserService注入UserDao
- UserService执行其他的生命周期过程,最终完成Bean的创建,存储到一级缓存中,删除二三级缓存。
Spring中Aware接口
可以在类的内部得到BeanFactory等Spring组件
public class UserServiceimpl implements UserService, InitializingBean, ServletConfigAware, ApplicationContextAware, BeanFactoryAware, BeanNameAware {
// 缺少web环境所以并不会执行
@Override
public void setServletConfig(ServletConfig servletConfig) {
System.out.println(servletConfig);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println(beanFactory);
}
@Override
public void setBeanName(String s) {
System.out.println(s);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println(applicationContext);
}
}