Spring框架中,一旦把一个Bean归入到Spring IoC容器之中,这个Bean的生命周期就会交由容器进行管理,通常担当管理者角色的是BeanFactory或ApplicationContex。web
BeanDefinition:用于管理各类对象以及它们之间相互依赖关系的核心数据结构。spring
Resource:用来封装IO操做的类。编程
收集过程:经过refresh方法启动,包括BeanDefinition和Resource的定位、载入、注册三个基本过程:缓存
-- 定位:即寻找数据的过程,指对BeanDefinition的资源定位,由ResourceLoader经过统一的Resource接口完成。
-- 载入:把用户定义好的Bean表示成IOC容器的内部数据结构,即BeanDefinition(POJO对象在IOC容器中的抽象)
-- 注册:将BeanDefinition注入到HashMap中,IOC容器就是经过这个HahMap来管理数据。
Spring 的容器最基本的接口就是:BeanFactory。BeanFactory 负责配置、建立及管理bean。数据结构
调用者只需使用getBean 方法便可得到指定bean的引用,无须关心bean 的实例化过程。即bean 实例的建立过程彻底透明。app
经过BeanFactory获取Bean框架
在UserService中注入tool字段,经过BeanFactory来实现获取函数
UserService实现BeanFactoryAware接口的setBeanFactory方法,Spring会调用setBeanFactory方法将BeanFactory注入到UserService的factory字段(须要注意UserService须要被实例化,能够经过xml来配置bean,也能够经过@component类的注解来将Bean装载到容器实例化),而后就能够经过setBeanFactory获取Bean。post
获取Bean推荐使用ApplicationContext,由于其是BeanFactory 的子接口,提供了更多面向应用的功能。ui
经过ApplicationContext获取Bean:
和BeanFactory同样,SpringConfigTool类也须要实例化,ApplicationContext才能被注入到context字段上,能够经过XML或者@component类型的注解,将Bean注入。
1. BeanFacotry延迟加载,即只有在使用到某个Bean时(调用getBean()),才对该Bean
进行加载实例化,若是Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次
使用调用getBean方法才会抛出异常;而ApplicationContext则在初始化自身是检验,
这样有利于检查所依赖属性是否注入;因此一般状况下咱们选择使用
ApplicationContext。ApplicationContext则会在上下文启动后预载入全部的单
实例Bean。经过预载入单实例bean ,确保当你须要的时候,你就不用等待,由于它们
已经建立好了。
2. 一旦单例被实例化就会被放入缓存Bean池,下次获取直接返回,而多例则每一次都建立
一个新对象返回,并将控制权移交给用户,由用户管理Bean的生命周期,使用完后须要
显示设置为null,帮助回收。BeanFactory只能管理单例Bean,而
ApplicationContext也能够管理多例Bean。
3. BeanFactory和ApplicationContext都支持BeanPostProcessor、
BeanFactoryPostProcessor的使用,但二者之间的区别是:BeanFactory须要手动
注册,而ApplicationContext则是自动注册。(Applicationcontext比
beanFactory 加入了一些更好使用的功能。并且 BeanFactory的许多功能须要经过
编程实现而 Applicationcontext 能够经过配置实现。好比后处理 bean ,
Applicationcontext 直接配置在配置文件便可而 BeanFactory这要在代码中显示
的写出来才能够被容器识别)。
4. BeanFactory主要是面对与 Spring 框架的基础设施,面对 spring 本身。而
Applicationcontext主要面对与 Spring 使用的开发者。基本都会使用
Applicationcontext并不是 BeanFactory。
2. Bean 的生命周期
BeanFactory实例化Bean属性相关实例化顺序
一、调用Bean的默认构造方法,或者在指定的构造方法,生成bean实例(暂称为instance1);
三、若是Bean的配置文件中注入了Bean属性值,则在instance1基础上进行属性注入造成instance2,这种注入是覆盖性的。
二、若是Bean实现了InitializingBean接口,则调用afterPropertiesSet()方法,来改变或操做instance2,获得instance3;
四、若是Bean的配置文件中指定了init-ethod="init"属性,则会调用指定的初始化方法,则在instance3的基础上调用初始化方法init(),将对象最终初始化为instance4;初始化的名字任意。
Bean的具体加载与初始化
实例化一个Bean(由BeanFactory读取Bean定义文件,并生成各个实例)--也就是咱们常说的new;
按照Spring上下文对实例化的Bean的属性值进行设置--也就是IOC注入;
若是这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String)方法,此处传递的就是Spring配置文件中Bean的id值
若是这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory(setBeanFactory(BeanFactory)传递的是Spring工厂自身(能够用这个方式来获取其它Bean,只需在Spring配置文件中配置一个普通的Bean就能够);
若是这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文(一样这个方式也能够实现步骤4的内容,但比4更好,由于ApplicationContext是BeanFactory的子接口,有更多的实现方法);
若是这个Bean关联了BeanPostProcessor接口,将会调用postProcessBeforeInitialization(Object obj, String s)方法
初始化以前构造注入依赖以后执行
通常是用来在实例构造完成后,实例的应该注入的依赖属性已经完成注入,须要对不须要注入的实例属性进行自定义初始化配置;固然也可指定一个init-method方法完成初始化,二者的做用同样,都是完成用户自定义初始化。对于单例,若是bean实现了InitializingBean接口则afterPropertiesSet方法只会被调用一次;不然每次建立bean时afterPropertiesSet方法都会被从新调用。
或者使用@PostConstruct后构造注解来将任意方法名称的方法标明为一个init-method方法
注:以上工做完成之后就能够应用这个Bean了,若是这个Bean是一个Singleton的,则将这准备就绪的Bean放入Spring缓存池中,已被下次使用,因此通常状况下咱们调用同一个id的Bean会是在内容地址相同的实例,固然在Spring配置文件中也能够配置非Singleton,此时不会将Bean放入缓存池中,而是直接将控制权交给Bean的使用者。
当Bean再也不须要时,会通过清理阶段,若是Bean实现了DisposableBean这个接口,会调用那个其实现的destroy()方法;
最后,若是这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。
可使用@PreDestroy前销毁注解,标明一个方法为destroy-method
说明: 若是Bean是由BeanFactory管理,则没有第五步,一样若是由ApplicationContext管理,则没有第四步。
摘自Spring BeanFactoy官方文档:
Bean factory implementations should support the standard bean lifecycle interfaces as far as possible. The full set of initialization methods and their standard order is:
-- BeanNameAware's setBeanName
-- BeanClassLoaderAware's setBeanClassLoader
-- BeanFactoryAware's setBeanFactory
-- EnvironmentAware's setEnvironment
-- EmbeddedValueResolverAware's setEmbeddedValueResolver
-- ResourceLoaderAware's setResourceLoader (only applicable when running in an application context)
-- ApplicationEventPublisherAware's setApplicationEventPublisher (only applicable when running in an application context)
-- MessageSourceAware's setMessageSource (only applicable when running in an application context)
-- ApplicationContextAware's setApplicationContext (only applicable when running in an application context)
-- ServletContextAware's setServletContext (only applicable when running in a web application context)
-- postProcessBeforeInitialization methods of BeanPostProcessors
-- InitializingBean's afterPropertiesSet
-- a custom init-method definition
-- postProcessAfterInitialization methods of BeanPostProcessors
On shutdown of a bean factory, the following lifecycle methods apply:
-- postProcessBeforeDestruction methods of DestructionAwareBeanPostProcessors
-- DisposableBean's destroy
-- a custom destroy-method definition
@Resource
默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入;
@Autowired
默认是按照类型装配注入的,若是想按照名称来转配注入,则须要结合@Qualifier一块儿使用;
@Resource
注解是又J2EE提供,而@Autowired是由spring提供,故减小系统对spring的依赖建议使用@Resource的方式;若是Maven项目是1.5的JRE则需换成更高版本的。
@Resource和@Autowired均可以书写注解在字段或者该字段的setter方法之上
@Autowired
能够对成员变量、方法以及构造函数进行注释,而 @Qualifier 的注解对象是成员变量、方法入参、构造函数入参。
@Qualifier("XXX")
中的 XX是 Bean 的名称,因此 @Autowired 和 @Qualifier 结合使用时,自动注入的策略就从 byType 转变成 byName 了。
@Autowired 注释进行自动注入时
Spring 容器中匹配的候选 Bean 数目必须有且仅有一个,经过属性required能够设置非必要。