依赖注入发生的时间
当 Spring IOC 容器完成了 Bean 定义资源的定位、载入和解析注册以后,IOC 容器中已经管理类 Bean 定义的相关数据,但是此时 IOC 容器还没有对所管理的 Bean 进行依赖注入,依赖注入在以下两种情况 发生:
- 用户第一次调用 getBean()方法时,IOC 容器触发依赖注入。
- 当用户在配置文件中将元素配置了 lazy-init=false 属性,即让容器在解析注册 Bean 定义 时进行预实例化,触发依赖注入。
DI大致流程
1 AbstractBeanFactory 的 getBean()方法调用自己的doGetBean()
定义了根据 Bean 定义的模式,采取的不同创建 Bean 实例对象的策略。在 Spring 中,如果 Bean 定义的单例模 式(Singleton),则容器在创建之前先从缓存中查找,以确保整个容器中只存在一个实例对象。如果 Bean 定义的是原型模式(Prototype),则容器每次都会创建一个新的实例对象。除此之外,Bean 定义还可以 扩展为指定其生命周期范围。
2 AbstractAutowireCapableBeanFactory执行createBean()调用自己的doCreateBean()
创建容器指定的 Bean 实例对 象,同时还对创建的 Bean 实例对象进行初始化处理
1)、createBeanInstance()方法,生成 Bean 所包含的 java 对象实例。
根据指定的初始化策略,使用简单工厂、工厂方法或者容器的自动装 配特性生成 Java 实例对象
2)、populateBean()方法,对 Bean 属性的依赖注入进行处理
执行applyPropertyValues() : 属性值类型不需要强制转换时,不需要解析属性值,直接准备进行依赖注入。属性值需要进行类型强制转换时,如对其他对象的引用等,首先需要解析属性值,然后对解析后的 属性值进行依赖注入
3 BeanDefinitionValueResolver的resolveValueIfNecessary()方法
具体执行上面解析属性注入规则
4 AbstractNestablePropertyAccesso的setPropertyValue
对容器中完成初始化的 Bean 实例对象进行属性的依赖注入,即把 Bean 对象设置到它所依赖的另一个 Bean 的属性中去
1)、对于集合类型的属性,将其属性值解析为目标类型的集合后直接赋值给属性。
2)、对于非集合类型的属性,大量使用了 JDK 的反射机制,通过属性的 getter()方法获取指定属性注入 以前的值,同时调用属性的 setter()方法为属性设置注入后的值。看到这里相信很多人都明白了 Spring 的 setter()注入原理。