spring容器默认在启动时就对bean进行实例化,但是可以修改baen的lazy-init属性为true延迟bean的初始化,使用bean时才实例化:
(1)spring中bean的scope默认是singleton,lazy-init为false,容器启动时实例化bean,修改lazy-init为true时,使用bean时实例化。
1 | <bean lazy-init="true"/> |
(2)scope是prototype时,lazy-init不管是true还是false都会在使用的时候才对bean实例化。
参考:
林兴洋的博客:spring中的bean何时被实例化
绝地反击T:Spring的IOC、Spring对象初始化bean时机、Spring容器生命周期
从容器中获取bean的过程如下:
1 | //使用FileSystemXmlApplicationContext加载配置文件 |
依赖注入的发生是在容器中的BeanDefinition数据已经建立好的前提下进行的,这个getBean方法就是触发依赖注入发生的地方,该方法在BeanFactory中有定义,DefaultListableBeanFactory的基类AbstractBeanFactory对该方法有实现,因此就从AbstractBeanFactory的getBean方法入手,看一下IoC容器依赖注入的过程。
1.AbstractBeanFactory
1 | public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory { |
(1)在doGetBean方法中,首先会从缓存中查找bean,如果未找到,则对IoC容器中BeanDefinition是否存在进行检查。检查时会从双亲BeanFactory中查找,如果当前双亲BeanFactory中找不到就顺着双亲BeanFactory链一直向上查找,如果没有双亲BeanFactory,就从当前BeanFactory中取。
(2)获取到bean的BeanDefinition后,会调用ObjectFactory的createBean方法对Bean进行实例化。
(3)实例化之后,会对创建的Bean进行类型检查,检查类型是否与实例化的bean一致,如果正确就返回这个新创建的bean。
2.AbstractAutowireCapableBeanFactory
AbstractAutowireCapableBeanFactory中实现了createBean方法。
1 | public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory |
doCreateBean中两个方法:
(1)createBeanInstance方法:
在这个方法中,又会调用instantiateBean和autowireConstructor创建bean的实例。
autowireConstructor中是通过ConstructorResolver的autowireConstructor方法完成bean的实例化的。
instantiateBean中,调用getInstantiationStrategy()返回了CglibSubclassingInstantiationStrategy对象,调用该对象的instantiate方法对bean实例化,从名字上就可以看出是通过CGLIB实例化的。CglibSubclassingInstantiationStrategy是SimpleInstantiationStrategy的子类,实际上先走的SimpleInstantiationStrategy的instantiate方法,在该方法中调用CglibSubclassingInstantiationStrategy的instantiateWithMethodInjection方法完成的。
SimpleInstantiationStrategy
1 | public class SimpleInstantiationStrategy implements InstantiationStrategy { |
SimpleInstantiationStrategy的instantiateWithMethodInjection只抛出了一个异常,其他的什么也没做。CglibSubclassingInstantiationStrategy对该方法进行了重写。
CglibSubclassingInstantiationStrategy
1 | public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationStrategy { |
CglibSubclassingInstantiationStrategy的instantiateWithMethodInjection方法中调用了CglibSubclassCreator的instantiate方法完成了bean的实例化。
(2)populateBean方法
该方法的作用是设置bean之间的依赖关系,完成整个依赖注入的过程。
回到AbstractAutowireCapableBeanFactory的populateBean方法:
1 | /** |
BeanWrapper是一个接口,setPropertyValues方法是在 AbstractNestablePropertyAccessor中实现的,BeanWrapperImpl又是AbstractNestablePropertyAccessor的子类,因此可以通过BeanWrapperImpl调用setPropertyValues方法完成属性值的设置。
1 | public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyAccessor { |
在Bean的创建和对象依赖注入的过程中,需要依据BeanDefinition中的信息递归的完成依赖注入,这些递归都是以getBean为入口的。一个递归是在上下文体系中查找需要的Bean和创建Bean的递归调用,另一个递归是在依赖注入时,通过递归调用容器的getBean方法,得到当前Bean的依赖,同时也触发对依赖Bean的创建和注入。对Bean的属性进行依赖注入时,解析的过程也是一个递归的过程。这样,根据依赖关系,一层一层的完成Bean的创建和注入,直到最后完成当然Bean的创建。
在Bean创建和依赖注入完成以后,在IoC容器中建立起一系列依靠依赖关系联系起来的Bean。
来自:spring技术内幕:深入解析spring架构与设计原理
Spring版本:5.0.5