bean的创建过程分析-finishBeanFactoryInitialization-01
作者:互联网
bean的创建过程分析-finishBeanFactoryInitialization-01
我们都知道spring中有两个启动类, 分别是
ClassPathXmlApplicationContext
和FileSystemXmlApplicationContext
。通常我们实际使用比较多得启动类就是
ClassPathXmlApplicationContext
。下面我们就来先简单的回忆一下该启动类启动的核心流程。
0、前言概述
我们先来看一下类的继承关系图 ,这里一定要知道 ClassPathXmlApplicationContext
构造方法中调用的refresh()
方法是父类AbstractXmlApplicationContext
类中的refresh()
方法。
我们都知道,要想搞懂spring源码,必须要搞清楚refresh()
源码。下图就是展示了大致的一个如何走到refresh()
方法的流程
然后今天我们主要讲解的就是refresh
方法中执行的finishBeanFactoryInitialization(beanFactory)
这一步。
1、finishBeanFactoryInitialization(beanFactory);
初始化bean讲解
finishBeanFactoryInitialization
方法中,依然是隶属于AbstractApplicationContext
类
refresh()
方法中一共执行了13个方法,今天我们具体讲讲 finishBeanFactoryInitialization(beanFactory);
这个方法 是如何实例化bean的过程。
1.1、第一部分概述 - ConversionService
处理
这部分,主要是向 spring 容器中添加 beanFactory 添加 一些类型转换服务, 具体的细节参见:
// Initialize conversion service for this context.
// 为上下文初始化类型转换器
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
Spring中类型转换服务ConversionService 以及 Converter 类型转换器
1.2、第二部分概述 - EmbeddedValueResolver
处理
这部分, 主要判断是否有 EmbeddedValueResolver
内嵌式值处理器,如果没有的话, 就添加该处理器
实际上,我们在 执行 invokeBeanFactoryPostProcessor(beanFactory)
的时候, 就已经处理过这部分了, 所以一般是进不来的,更多的是起到安全性考虑的保护作用。
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
1.3、第三部分概述-LoadTimeWeaverAware
处理
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
// 尽早初始化loadTimeWeaverAware bean,以便尽早注册它们的转换器
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
其实这部分中的 LoadTimeWeaverAware
主要是为了后面的面向切面服务的, 其实我们在prepareBeanFactory
环节中就已经添加了相应的织入执行器
正如截图中的注解所言:
LoadTimeWeaverAware
主要是在AOP中进行使用的, 后面我们讨论AOP的时候在进行补充
1.4、第四部分概述- TempClassLoader
& freezeConfiguration
这部分怎么理解呢?
-
这部分主要是做实例化之前的禁止操作,实例化之前,我们不希望beanFactory中的bean定义信息
BeanDefinition
再有修改。所以存在上述的一些操作 -
beanFactory.setTempClassLoader(null);
即 精致使用临时类加载器, 在进行类型匹配操作了,即不希望再有类的一些定义信息再加入到``beanFactory`了。 -
beanFactory.preInstantiateSingletons();
即 冻结所有的BeanDefinition
定义, 说明注册的bean定义将不被修改或者任何进一步的处理。-
public void freezeConfiguration() { this.configurationFrozen = true; this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames); }
-
这里主要做了两件事
- 设置冻结的标志位
- 将所有的冻结的
BeanDefinitionNames
即bean定义信息的名称, 添加到frozenBeanDefinitionNames
字符串数组中去。
-
1.5、第五部分概述- preInstantiateSingletons
这个步骤非常重要, 核心作用就是预先实例化所有单例bean
// 实例化剩下的单例对象
beanFactory.preInstantiateSingletons();
具体讲解,我会单独拿出来说明。。。
1.5.1、下面我们结合一个FactoryBean接口的使用
,分析一下FactoryBean
和 BeanFactory
的区别
- 实现一个
Car
汽车类
package com.qzk.QzkFactoryBeanDir;
/**
* @ClassName Car
* @Description 汽车实现类
* @Author qzk
* @Date 2022/5/9 11:30 上午
* @Version 1.0
**/
public class Car {
/**
* 名称
*/
private String name;
/**
* 品牌
*/
private String brand;
/**
* 速度
*/
private Integer speed;
public Car() {
}
public Car(String name, String brand, Integer speed) {
this.name = name;
this.brand = brand;
this.speed = speed;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public Integer getSpeed() {
return speed;
}
public void setSpeed(Integer speed) {
this.speed = speed;
}
@Override
public String toString() {
return "Car{" +
"name='" + name + '\'' +
", brand='" + brand + '\'' +
", speed='" + speed + '\'' +
'}';
}
}
- 实现一个继承
FactoryBean
接口的类,重写getObject()
方法,返回Car
对象。
package com.qzk.QzkFactoryBeanDir;
import org.springframework.beans.factory.FactoryBean;
/**
* @ClassName CarFactoryBean
* @Description 实现了 FactoryBean 接口的 CarFactoryBean 汽车工厂
* @Author qzk
* @Date 2022/5/9 11:29 上午
* @Version 1.0
**/
public class CarFactoryBean implements FactoryBean<Car> {
private String carInfo;
public CarFactoryBean(String carInfo) {
this.carInfo = carInfo;
}
public String getCarInfo() {
return carInfo;
}
public void setCarInfo(String carInfo) {
this.carInfo = carInfo;
}
@Override
public Car getObject() throws Exception {
Car car = new Car();
String[] splits = carInfo.split(",");
car.setName(splits[0]);
car.setBrand(splits[1]);
car.setSpeed(Integer.valueOf(splits[2]));
return car;
}
@Override
public Class<?> getObjectType() {
return Car.class;
}
@Override
public boolean isSingleton() {
return FactoryBean.super.isSingleton();
}
}
- 编写xml配置文件
testFactoryBean.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">
<!-- 直接创建car1 这个bean -->
<bean id="car1" class="com.qzk.QzkFactoryBeanDir.Car" >
<constructor-arg name="brand" value="奔驰"></constructor-arg>
<constructor-arg name="name" value="E300"></constructor-arg>
<constructor-arg name="speed" value="200"></constructor-arg>
</bean>
<!-- 利用无参构造, 结合 property 属性赋值的方式创建bean -->
<bean id="car2" class="com.qzk.QzkFactoryBeanDir.CarFactoryBean" >
<property name="carInfo" value="总裁,玛莎拉蒂,251"></property>
</bean>
<!-- 利用有参构造 结合 constructor-arg 参数传递的方式创建bean -->
<bean id="car3" class="com.qzk.QzkFactoryBeanDir.CarFactoryBean">
<constructor-arg name="carInfo" value="卡宴,保时捷,250"></constructor-arg>
</bean>
</beans>
- 编写测试启动类
TestFactoryBean
package com.qzk.QzkFactoryBeanDir;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @ClassName TestFactoryBean
* @Description 测试 实现了FactoryBean接口的测试类
* @Author qzk
* @Date 2022/5/9 11:51 上午
* @Version 1.0
**/
public class TestFactoryBean {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("testFactoryBean.xml");
Car car = (Car) context.getBean("car1");
System.out.println(car); // Car{name='E300', brand='奔驰', speed='200'}
Car car2 = (Car)context.getBean("car2");
System.out.println(car2); // Car{name='总裁', brand='玛莎拉蒂', speed='251'}
CarFactoryBean bean = (CarFactoryBean) context.getBean("&car2");
System.out.println(bean); // com.qzk.QzkFactoryBeanDir.CarFactoryBean@1d29cf23
CarFactoryBean carFactoryBean = context.getBean("&car2",CarFactoryBean.class);
System.out.println(carFactoryBean); // com.qzk.QzkFactoryBeanDir.CarFactoryBean@1d29cf23
Car car21 = context.getBean("car2", Car.class);
System.out.println("car2 是单例模式, 所以再工厂bean中获取的car2 应该是同一个bean,所以相同:" +(car21 == car2));
Car car3 = (Car) context.getBean("car3");
System.out.println(car3);
Object car31 = context.getBean("car3");
System.out.println("car3 是原型模式,所以这边应该是不等的:"+ (car31 == car3));
//
}
}
1.5.2、源码分析beanFactory.preInstantiateSingletons()
我们在上面的xml中分别定义个 car1 & car2 & car3
,同样,spring 在读取的时候, 也会按照这个顺序依次去创建car
。
- 创建
car1
普通bean 的执行流程
大致的一个 bean创建流程 遵循如下如所示:
在 执行doCreateBean
的过程中, 会根据 bean的类型, bean的定义信息(是否单例,是否原型, 是否懒加载, 是否初始化, 之类的信息, 做一些相关的处理工作,),并且会判断是否是工厂类, 以及是否是静态工厂,以及实例工厂等方式去执行不同的实例化步骤。
标签:01,String,beanFactory,Car,finishBeanFactoryInitialization,bean,speed,public 来源: https://www.cnblogs.com/qianzhengkai/p/16257658.html