spring源码学习(八)bean的创建
一、创建容器中的所有剩余单例对象,在AbstractApplicationContext里finishBeanFactoryInitialization方法
1、如果存在自定义的ConversionService,把这个bean设置给beanFactory的conversionService,方便后续使用。
ConversionService的作用:转换参数类型有三个重要的接口
1)、Converter<S, T> 把S类型转换为T类型
2)、GenericConverter 把一个类型转换为多个类型
3)、ConverterFactory 代码注释can convert objects from S to subtypes of R,能把对象S转换成R的子类型
如何自定义实现自己的ConversionService,在spring的官网也有介绍

2、注册一个值处理器如果没有类似于PropertyPlaceholderConfigurer这样的BPP,这个内嵌的值处理器可能在前面添加,也可能在处理添加
3、LoadTimeWeaverAware
4、beanFactory.freezeConfiguration(),冻结所有的beanDefinition;后面的步骤开始实例化bean,所以不在允许修改beanDefinition
5、preInstantiateSingletons(),开始挨个遍历beanNames,并创建bean
二、preInstantiateSingletons()
1、getMergedLocalBeanDefinition:如果存在父容器,从父容器中拿到对应的beanDefinition与当前的beanDefinition进行合并,放到缓存中并返回;如果不存在父容器,那么把当前beanDefinition组装成RootbeanDefinition放入缓存,并返回
2、判断当前需要创建的bean是否是非抽象的、单例的、非懒加载的,满足这些条件才会进行创建
3、判断是否是factoryBean,如果是factoryBean,那么走factoryBean的创建流程;否则走标准bean创建流程
首先,都是对象工厂,用来创建对象实例。如果使用beanFactory接口,那么创建的bean必须遵守springbean的生命周期,从实例化->填充属性->执行initAwareMehtod->执行BPP的before->执行initMethod->执行BPP的after。而factoryBean创建简单便捷,只需要调用getObject()方法就可以返回具体的对象
如何使用factoryBean:
1)、实现实现FactoryBean接口,里有三个方法:一是getObject返回具体对象,二是getObjectType需要返回对象的类型,三是isSingleton是否是单例的。如果是单例的会放到factoryBeanObjectCache里交给spring管理与标准流程创建的单例bean放入的缓存容器不一致
2)、在配置文件中配置自定义的factoryBean,交给spring管理
3)、从容器中获取具体的bean对象
如果我们需要获取工厂bean在获取的时候需要加&符号,表示我们当前需要获取的是工厂bean,而不是需要工厂产生的bean对象

4)、User bean = (User)context.getBean("factoryBean"),获取所需的bean的流程

三、doGetBean()
1、transformedBeanName(name)转换beanName 看是否包含&符号,如果包含则去掉
2、getSingleton(beanName),从缓存中获取
3、判断缓存中获取到bean并且参数为空,调用getObjectForBeanInstance,判断是否需要进入factoryBean生产对象
4、是否存在父容器,如果存在,并且当前容器没有beanName的定义信息,那么直接调用父容器的getBean获取
5、获取beanName的依赖对象,如果存在依赖关系,首先注册依赖,然后先获取需要依赖的bean,再执行后续的流程
6、判断bean的作用域,执行具体的创建逻辑
四、createBean()
1、锁定Class,resolveBeanClass根据给定的beanName来解析class
2、验证覆盖的方法,有两个属性lookup-method,replace-method就是在这里执行的
3、给BPP一个机会去创建代理对象resolveBeforeInstantiation
如果有定义这样的一个BPP实现了InstantiationAwareBeanPostProcessor接口那么就会调用接口的两个方法,实例化前和实例化后的执行逻辑

4、调用doCreateBean,真正创建bean的方法
五、doCreateBean
1、createBeanInstance
1)、判断是否有factoryMethod如果有,那么就使用factoryMehtod定义的方式去创建bean
如果只是使用factory-method标签,那么定义的方法就必须是静态的方法

如果定义的是普通方法,就必须指定factory-bean指向

2)、判断BD中是否已经存在合适的构造方法,如果存在则直接开始实例化,如果不存在则执行后续的逻辑
3)、找到合适的构造器determineConstructorsFromBeanPostProcessors,如果找到使用对应的构造器进行实例化调用autowireConstructor;如果没有找到,则调用默认构造器进行实例化调用instantiateBean。并把结果包装到BeanWrapper中返回
spring中实例化的几种方式
1、反射
2、通过BPP代理创建(resolveBeforeInstantiation)
3、supplier
4、factoryBean
5、factoryMethod
2、applyMergedBeanDefinitionPostProcessors,允许BPP修改合并的 bean 定义
这里主要涉及到两个BPP
1)AutowiredAnnotationBeanPostProcessor,解析@Autowired、@Value
2) CommonAnnotationBeanPostProcessor,解析@PostConstruct、@PreDestroy、@Resource等注解

3、放入到三级缓存,addSingletonFactory,放入的对象是lambda表达式

4、populateBean填充属性,循环依赖就是在这个地方产生的
1)、获取BD中需要填充属性的集合mbd.getPropertyValues();
2)、执行InstantiationAwareBeanPostProcessors接口的postProcessAfterInstantiation方法,可以去改变bean的状态,如果任意接口返回了false,那么就不继续填充属性,直接返回了
3)、判断属性的自动装配方式如果是byType则调用autowireByType获取属性值,如果是byName则调用autowireByName获取属性值
4)、执行InstantiationAwareBeanPostProcessors接口的postProcessPropertyValues方法,例如AutowiredAnnotationBeanPostProcessor中的@Autowired、@Value属性注入就是在这里完成的;以及CommonAnnotationBeanPostProcessor
5)、applyPropertyValues真正的填充属性的操作
5、initializeBean初始化bean
1)、首先执行invokeAwareMethods,包括BeanFactoryAware、BeanNameAware、BeanClassLoaderAware
2)、执行BPP的before方法,比较重要的ApplicationContextAwareProcessor,在此会注入EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware

3)、调用初始化方法
首先判断当前bean是否实现了InitializingBean接口,如果实现了该接口,则调用它的afterPropertiesSet方法,该方法的调用必须在所有属性值都注入后的情况下。可以在此方法检查配置是否正确
然后执行自定义的初始化方法,有两种方式。一是:在配置文件中配置init-method属性,二是:在方法上添加添加@PostConstruct注解。可以都标识在同一个方法上,但是只会执行一次
4)执行BPP的after方法,这里最重要的是AbstractAutoProxyCreator,如果不需要提前创建动态代理,那么都在这里生成动态代理对象
6、registerDisposableBeanIfNecessary注册bean的销毁方法如果有指定的话


浙公网安备 33010602011771号