Spring Bean 生命周期
- Spring Bean 元信息配置阶段
- Spring Bean 元信息解析阶段
- Spring Bean 注册阶段
- Spring BeanDefinition 合并阶段
- Spring Bean Class 加载阶段
- Spring Bean 实例化前阶段
- Spring Bean 实例化阶段
- Spring Bean 实例化后阶段
- Spring Bean 属性赋值前阶段
- Spring Bean Aware接口回调阶段
- Spring Bean 初始化前阶段
- Spring Bean 初始化阶段
- Spring Bean 初始化后阶段
- Spring Bean 初始化阶段完成阶段
- Spring Bean 销毁前阶段
- Spring Bean 销毁阶段
- Spring Bean 垃圾收集
- 面试题
Spring Bean元信息配置,解析阶段
BeanDefinition XML,properties配置以及解析
- 面向资源配置
- XML配置
- Properties资源配置
- 面向注解
- 面向API
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
/* Xml配置读取 */
// XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
// String xmlPath = "";
// reader.loadBeanDefinitions(xmlPath);
PropertiesBeanDefinitionReader reader = new PropertiesBeanDefinitionReader(beanFactory);
String location = "META-INF/user.properties";
ClassPathResource resource = new ClassPathResource(location);
EncodedResource encodedResource = new EncodedResource(resource, "UTF-8");
int i = reader.loadBeanDefinitions(encodedResource);
System.out.println("已加载数量" + i);
// String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
// BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanDefinitionNames[0]);
// System.out.println(beanDefinitionNames);
System.out.println(beanFactory.getBean( User.class));
}
如果在properties
文件中进行注册Bean,需要注意,注册class的时候需要注意 .(class)
user.(class) = edu.ahau.thinking.in.spring.ioc.overview.domain.User
在properties
文件使用中文可能会出现乱码,因此需要使用EncodedResource
进行转码;
注解配置以及解析
public class AnnotatedBeanDefinitionParsingDemo {
public static void main(String[] args) {
DefaultListableBeanFactory registry = new DefaultListableBeanFactory();
// 基于java注解的 BeanDefinitionReader
AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(registry);
// 对BeanNameGenerator重新实现,并且重新注入
MyBeanNameGenerator myBeanNameGenerator = new MyBeanNameGenerator();
reader.setBeanNameGenerator(myBeanNameGenerator);
int beanNumberNumsBefore = registry.getBeanDefinitionCount();
// 注册当前类(非component)
reader.register(AnnotatedBeanDefinitionParsingDemo.class);
int beanNumberNumsAfter = registry.getBeanDefinitionCount();
System.out.println("已加载BeanDefinition数量: "+(beanNumberNumsAfter - beanNumberNumsBefore));
// 普通的class作为Component注册到SpringIoC容器后,通常Bean名称为小驼峰
// AnnotationBeanNameGenerator对BeanName的构造
System.out.println(registry.getBean("haha"));
}
}
在上面代码自定义实现了BeanNameGenerator,因此没有使用小驼峰BeanName获取Bean,而是自定义的"haha
"
public class MyBeanNameGenerator implements BeanNameGenerator {
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
return "haha";
}
}
Spring Bean 注册阶段
注册过程在org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition
中;
源码查看,并分析:
// 存储beanDefinition
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
// 保证创建Bean的顺序
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
/* 对beanName和beanDefinition进行空判断 */
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
/* 校验Bean的定义 */
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
// 获取已经存在的beanDefinition
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
/* bean的覆盖 */
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
/* 创建Bean */
else {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
Spring BeanDefinition 合并阶段
先看xml
<!-- RootBeanDefinition ,不需要进行合并 -->
<bean id="user" class="edu.ahau.thinking.in.spring.ioc.overview.domain.User">
<property name="age" value="12"/>
<property name="workCities" value="BEIJING,HANGZHOU"/>
<property name="cityList" value="BEIJING,SHANGHAI"/>
</bean>
<!-- 普通BeanDefinition定义,GenericBeanDefinition -->
<bean id="superUser" class="edu.ahau.thinking.in.spring.ioc.overview.domain.SuperUser" primary="true" parent="user">
<property name="address" value="anhui"/>
</bean>
在BeanDefinition中存在String getParentName();
获取的值就是<bean>
标签里面的parent
;
user是使用RootBeanDefinition
进行定义的,所以不存在parent
,但是依然需要使用GenericBeanDefinition
进行定义
superUser就是使用GenericBeanDefinition
进行定义,使用org.springframework.beans.factory.support.BeanDefinitionBuilder#genericBeanDefinition(java.lang.String)
构建出一个BeanDefinition
;
在<bean>
标签里面写上parent,就会把parentBean
注入到当前Bean中,就如上述user
的信息放入superUser
中;
根据依赖查找的Demo
public class MergedBeanDefinitionDemo {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("classpath:\\META-INF/dependency-looKup-context.xml");
User user = beanFactory.getBean("user", User.class);
System.out.println(user);
SuperUser superUser = beanFactory.getBean("superUser", SuperUser.class);
System.out.println(superUser);
}
}
output: superUser里面包含着user的信息
User{name=‘null’, age=12, beanName=‘user’, workCities=[BEIJING, HANGZHOU], cityList=[BEIJING, SHANGHAI]}
SuperUser{address=‘anhui’}User{name=‘null’, age=12, beanName=‘superUser’, workCities=[BEIJING, HANGZHOU], cityList=[BEIJING, SHANGHAI]}
跟着Debug一步一步的来
User:
- org.springframework.beans.factory.support.AbstractBeanFactory#getMergedBeanDefinition(java.lang.String, org.springframework.beans.factory.config.BeanDefinition, org.springframework.beans.factory.config.BeanDefinition)
入的Bean是user,因为Demo里是依赖查找是按照顺序的;
GenericBeanDefinition转换成RootBeanDefinition
superUser:
如果存在,存在了user这个Bean,通过一系列操作到达这一步,overrideFrom()是对parent里面属性进行覆盖或者添加到superUser这个Bean;最后还是转换成RootBeanDefinition.
Spring Bean Class 加载阶段
- ClassLoader类加载
- Java Security 安全控制
- ConfigurableBeanFactory临时ClassLoader
String类型的BeanName转换为Class对象的阶段
Spring Bean 实例化前阶段
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("classpath:\\META-INF/dependency-looKup-context.xml");
System.out.println(beanFactory.getBean("superUser")); //SuperUser{address='null'}User{name='null', age=0, beanName='null', workCities=null, cityList=null} 被拦截
}
static class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
// 拦截superUser
if (ObjectUtils.nullSafeEquals("superUser", beanName) && SuperUser.class.equals(beanClass)) {
return new SuperUser();
}
return null;
}
}
postProcessBeforeInstantiation —> applyBeanPostProcessorsBeforeInstantiation —> 、
Spring Bean 实例化阶段
- 传统实例化方式
- 实例化策略 - InstantiationStrategy