Spring IOC(5) Spring Bean的创建 上
到目前为止,Spring源码中AbstractApplicationContext#refresh方法的已经解读到第11个方法finishBeanFactoryInitialization,前10个方法介绍了:
BeanFactory的准备,创建,刷新,个性化BeanFactory的扩展点,自定义属性解析;- 环境信息
Environment的加载(包括环境变量、系统变量等); BeanDefinition的加载,解析;BeanFactoryPostProcessor的注册与执行流程,BeanDefinitionRegistryPostProcessor的解析,ConfigurationClassPostProcessor对Spring注解的解析过程(@Component、@PropertySources、@PropertySource、@ComponentScans、@ComponentScan、@Import等注解的解析)BeanPostProcessor的注册流程;- 国际化,
Spring事件驱动的加载执行过程;
在前面,通过注解或XML的方式解析生成了BeanDefinition,接下来就是Spring最为核心的,根据BeanDefinition实例化Bean,并且对Bean的属性进行依赖注入。

其中Spring给了我们众多的扩展点,也涉及到面试常问的点——循环依赖的问题,本章我们探讨较为简单的内容——Spring怎么实例化一个Bean,根据JavaSE知识,我们知道实例化一个Bean 可以通过new or 反射的方式,Spring也不外呼这两种方式
前期准备
finishBeanFactoryInitialization 解析过程
1 | protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { |
这个方法的大致流程:
- 判断是否存在转换服务,有就设置,
Spring转换器接口ConversionService的默认实现是DefaultConversionService,这个默认的转换器实现中,内置了很多的转换器 - 判断是否有内置的值解析器,没有就创建一个处理占位符的解析器
- 实例化
LoadTimeWeaverAware,这里从容器中获取了AOP的织入,如果有的话就开始进行早期的Bean的创建 - 停止使用临时的类加载器
- 冻结
BeanDefinition的元数据信息,防止被修改 - 开始实例化所有的单例bean对象
除了beanFactory.preInstantiateSingletons() 方法,其他都是Bean创建的准备,接下来一个一个分析,首先是转换服务的设置。
Bean 的创建步骤
在Spring源码中对Bean的创建遵循一个步骤就是:getBean –> doGetBean –> createBean –> doCreateBean ,常规的Bean的创建过程都是按照这个步骤执行,然后反射实例化,属性填充,初始化,放到一级缓存中。那么非常规的有可能就不遵循这个步骤,比如FactoryBean,InstantiationAwareBeanPostProcessor 等。
DefaultListableBeanFactory#preInstantiateSingletons
1 |
|
Spring前期解析bean后解析 出来的BeanDefinition放入两个集合BeanDefinitionMap 和BeanDefinitionNames,这里遍历的是BeanDefinitionNames这个集合,存放的是beanName。
进行了BeanDefinition的合并处理,最终返回的全是RootBeanDefinition
1 | protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException { |
FactoryBean
FactoryBean是用来创建Bean对象的,他是一个接口,方法:
getObject获取bean对象getObjectType获取bean的类型isSingleton是否是单例的,默认是true
在创建对象时,你可以直接在getObject方法中进行new,或者反射,或者是其他都可以,非常的灵活。
1 | public class MyFactoryBean implements FactoryBean<MyUser> { |
FactoryBean 创建Bean的时候,如果xml注册的是一个FactoryBean的实现,但是获取出来又是具体的MyUser对象,这里Spring使用了懒加载的机制,在Spring 对Bean进行初始化时,实际上只将FactoryBean的实现类注册到了Spring容器中,当我们需要使用的时候,才去判断,如果是FactoryBean类型的,那么就去调用getObject方法去创建对象。如果是第二次去获取Bean,那么是从缓存中获取的,如果是获取&前缀的Bean,那就直接返回。

BeanFactory 和FactoryBean 的区别?
BeanFactory是一个Bean的创建工厂,比如AbstractApplicationContext就是BeanFactory的实现类,这个类就是用来创建Bean的,创建出来的Bean放在缓存中。
FactoryBean就是Bean实例,是由BeanFactory创建的,并且FactoryBean也是用来创建Bean对象,使用getObject方法进行创建,也是会放在缓存中供下次直接获取,而且如果在使用时需要使用FactoryBean的实例时需要以&前缀才能获取到,比如getBean("&myFactoryBean"); 如果是获取通过getObject方法创建的对象时,就不需要添加&前缀,比如getBean("myFactoryBean");
相同点:
- 都是用来创建对象的
- 都是创建出来之后放入缓存中供下次直接使用
不同点:
BeanFactory是一个对象创建工厂,而FactoryBean是一个Bean实例BeanFactory创建的对象一般来说都是使用反射调用构造函数创建的,而FactoryBean创建对象是调用getObject方法创建,并且创建方式不一定是通过反射,可以是直接new对象或者其他方式FactoryBean在获取对象时,可以获取到两个对象,一个是存放在BeanFactory创建的缓存中,通过&beanName获取的FactoryBean的实现类对象,一个是调用getObject创建的,通过beanName获取的具体对象。
单例Bean的创建
在创建时会调用getBean,然后doGetBean,一般来说在Spring中只要是do开头方法基本就是真正干活的方法
1 | protected <T> T doGetBean( |
去掉不重要的代码,可以看到首先是从缓存中获取,如果没有获取到就进行一些列检查,最终检查是否单例的Bean,此时这里的缓存为singletonObjects被称为一级缓存 是一个ConcurrentHashMap key是bean的名称
1 | protected Object getSingleton(String beanName, boolean allowEarlyReference) { |
如果是,那么就会调用getSingleton方法,传入一个beanName,一个ObjectFactory的lambda表达式,表达式中有个createBean方法,这个方法就是创建的Bean方法。
1 | sharedInstance = getSingleton(beanName, () -> { |
执行lambda表达式的具体方法时执行createBean
1 | public interface ObjectFactory<T> { |
getSingleton
1 | public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { |
我们可以发现这个getSingleton方法,功能是,如果当前bean在单例池没有,那么调用ObjectFactory的getObject方法获取,在外层其实调用了createBean方法,让我们来看看createBean
createBean
这个方法其实是在AbstractAutowireCapableBeanFactory中实现( DefaultListableBeanFactory的父类)AbstractAutowireCapableBeanFactory的定位是一个提供 bean 创建(使用构造函数解析)、属性填充、和初始化的BeanFactory
1 | protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) |
首先是进行了Bean的类型的解析,主要是用于后面的反射创建对象时使用,并设置到RootBeanDefinition中,然后进行方法覆盖操作。在里面遇到了重要bean的提前初始化,由resolveBeforeInstantiation实现。
提前初始化
这是spring给我们的一个扩展点。让对象可以提前创建,而不用再继续走doCreateBean方法里面的复杂逻辑,这样的话就提供给用户能够自己控制对象的创建过程以及执行增强等操作。
源码实现
1 | protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { |
InstantiationAwareBeanPostProcessor 是具备实例化感知能力的bean后置处理器,这里重点在于postProcessBeforeInstantiation 和 postProcessAfterInitialization 方法。
注意Instantiation 和 Initialization 的区别,前者是实例化(反射生成bean对象,任何属性都没有赋值,生成对象叫实例化)后者是初始化(属性赋值,初始化方法调用叫初始化)
applyBeanPostProcessorsBeforeInstantiation提供我们自己定一个bean,而不是spring帮我们反射生成bean的扩展,后续spring不会帮我们进行依赖注入applyBeanPostProcessorsAfterInitialization提供对bean进行代理的扩展,初始化后,我们可以对这个bean进行代理
使用
需要提前实例化的对象
1
2
3
4
5
6
public class MyBeforeInstantiation {
public void beforeInvoke(){
System.out.println("提前实例化,开始执行业务....");
}
}InstantiationAwareBeanPostProcessor的实现类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("beanName: " + beanName + "执行了 postProcessBeforeInstantiation 方法");
// 提前进行实例化
if (beanClass == MyBeforeInstantiation.class) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(beanClass);
enhancer.setCallback(new MyMethodInterceptor());
Object obj = enhancer.create();
System.out.println("创建对象:" + obj);
return obj;
}
return null;
}
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("beanName: " + beanName + "执行了 postProcessAfterInstantiation 方法");
return false;
}
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
System.out.println("beanName: " + beanName + "执行了 postProcessProperties 方法");
return pvs;
}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("beanName: " + beanName + "执行了 postProcessBeforeInitialization 方法");
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("beanName: " + beanName + "执行了 postProcessAfterInitialization 方法");
return bean;
}
}使用了CGLIB 动态代理去增强创建代理对象,编写一个回调拦截器:
1
2
3
4
5
6
7
8
9public class MyMethodInterceptor implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("方法执行前:"+method);
Object o1 = methodProxy.invokeSuper(o, objects);
System.out.println("方法执行后:"+method);
return o1;
}
}测试
1
2
3ApplicationContext ac = new AnnotationConfigApplicationContext(Context.class);
MyBeforeInstantiation bean = ac.getBean(MyBeforeInstantiation.class);
bean.beforeInvoke();
结果
1 | ... |
里只执行了两个方法,一个是postProcessBeforeInstantiation,是InstantiationAwareBeanPostProcessor的前置实例化接口,一个是postProcessAfterInitialization,是BeanPostProcessor的后置实例化接口。
doCreateBean
如果前面的InstantiationAwareBeanPostProcessor 没有返回一个bean 那么接下来就是spring容器为我们生成这个bean。
1 | protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) |
这里会先从缓存中获取FactoryBean实例化的对象,如果有就进行下面的逻辑,一般来说基本是获取不到的,来看 createBeanInstance
createBeanInstance
1 | protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { |
这里有2个扩展点,分别是2个return,意味着只要获取到Bean,那么就不需要进行下一步的执行
obtainFromSupplier
这里先用getInstanceSupplier获取Supplier,是BeanDefinition的方法,在解析BeanFactoryPostProcessor时可以进行BeanDefinition的处理。而在BeanFactoryPostProcessor接口注册和执行的时候,完全是可以自己定义一个BeanFactoryPostProcessor进行扩展实现。
这个属性位于AbstractBeanDefinition类中,一般来说用户自定义的BeanDefinition都是GenericBeanDefinition,而GenericBeanDefinition是继承这个抽象类的,所以我们在进行BFPP扩展实现时可以对GenericBeanDefinition设置这个属性值,这个属性值是一个Supplier函数式接口,相当于lambda表达式的用法,接下来自己实现一个验证一下。
创建一个
SupplierUser1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class SupplierUser {
private String username;
public SupplierUser() {
}
public SupplierUser(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String toString() {
return "SupplierUser{" +
"username='" + username + '\'' +
'}';
}
}创建一个创建
SupplierUser的类1
2
3
4
5public class CreateSupplier {
public static SupplierUser createUser(){
return new SupplierUser("redwinter");
}
}创建BFPP的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class SupplierBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("supplierUser");
// 获取原生的BeanDefinition
GenericBeanDefinition genericBeanDefinition = (GenericBeanDefinition) beanDefinition;
// 实例化Supplier
genericBeanDefinition.setInstanceSupplier(CreateSupplier::createUser);
// 设置类型
genericBeanDefinition.setBeanClass(CreateSupplier.class);
}
}测试类
1
2
3
4
5
6
public void SupplierBeanTest(){
ApplicationContext ac = new AnnotationConfigApplicationContext(Context.class);
SupplierUser bean = ac.getBean(SupplierUser.class);
System.out.println(bean);
}结果
1
SupplierUser{username='redwinter'}
FactoryMethod 对象的创建
这也是一个扩展点,根据源码可以看出这个属性也是在BeanDefinition中的,但是这个可以通过标签的方式进行设置,在Spring中factory-method创建Bean有两种方式,一种是静态工厂创建,一种是实例工厂创建。
目前创建bean的几种方式:
- 使用FactoryBean创建
- 使用InstantiationAwreBeanPostProcessor的前置实例化方法postProcessBeforeInstantiation进行创建
- 使用Supplier进行创建
- 使用factory-method标签进行创建
- 实例工厂创建(配合factory-bean标签)
- 静态工厂创建
- 反射创建(常规的,完整的创建流程)

下一篇继续介绍Bean的创建流程。
参考
https://www.cnblogs.com/redwinter/p/16241328.html





