因为一些事,已经有好几天没有更新过Blog了,今天花点时间继续补习Spring基础。
在Spring中,容器实现有BeanFactory和ApplicationContext两种,ApplicationContext扩展了BeanFactory。
简单来说Bean的生命周期分为定义、初始化、调用和销毁四个过程;但是在Spring的实际运行中非常复杂。
通过getBean方法获取一个Bean:
开始->调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation()方法->实例化
->调用InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation()方法
->调用InstantiationAwareBeanPostProcessor的postProcessPropertyValues()方法->设置属性值
->调用BeanNameAware的setBeanName()方法->调用BeanNameAware的setBeanFactory()方法
->调用BeanPostProcessor的postProcessBeforeInstantiation()方法->调用InitializingBean的afterPropertiesSet()方法
->通过init-method属性配置的初始化方法->调用BeanPostProcessor的postProcessAfterInstantiation()
|->prototype(将准备就绪的Bean交给调用者)
|->Singleton(Spring缓存池中准备就绪的Bean)->容器销毁(调用DisposableBean的afterPropertiesSet())
->通过destroy-method属性配置的销毁方法
(1)当调用者通过getBean(beanName)向容器请求一个Bean时,如果容器注册了InstantiationAwareBeanPostProcessor接口,在实例化Bean之前,将调用接口的postProcessBeforeInstantiation()方法;
(2)根据配置情况,调用Bean的构造方法或工厂方法实例化Bean;
(3)如果容器注册了InstantiationAwareBeanPostProcessor接口,在实例化bean之后,将调用接口的PostProcessAfterInstantiation()方法,可以在这里对已经实例化的对象进行一些操作;
(4)如果Bean配置了property属性,容器在这一步将配置值设置到Bean对应的属性中,不过在设置每个属性之前首先调用InstantiationAwareBeanPostProcessor接口的postProcessPropertyValues()方法;
(5)调用Bean的属性设置方法设置属性值;
(6)如果Bean实现了BeanNameAware接口,将调用setBeanName()接口方法,将配置的Bean名称设置到Bean中;
(7)如果Bean实现了BeanFactoryAware接口,将调用setBeanFactory()接口方法,将BeanFactory容器实例设置到Bean中;
(8)如果BeanFactory装配了BeanPostProcessor后处理器,将调用BeanPostPorcessor的Object postProcessBeforeInitialization(Object bean, String beanName)接口方法对Bean进行加工操作,返回的对象为加工处理后的Bean。用户可以通过该方法对某些Bean进行特殊处理,甚至改变Bean的行为,BeanPostProcessor在Spring框架占有重要地位,为容器提供Bean后续处理加工的切入点,Spring容器所提供的各种功能如Aop、动态代理等都是通过BeanPostProcessor来实现的;
(9)如果Bean实现了InitializingBean接口,将调用接口afterPropertiesSet()方法;
(10)如果在<bean>后通过init-method属性定义初始化方法,将执行这个方法;
(11)BeanPostProcessor后处理器定义了两个方法:postProcessBeforeInitialization()在第八步调用,Object postProcessAfterInitialization(Object bean, String beanName)方法在此时调用,容器再次获得对Bean进行加工的机会;
(12)如果在<bean>中指定Bean的作用范围为scope=“prototype”,将Bean返回给调用者,调用者负责Bean后续生命周期的管理,Spring不再管理这些bean的生命周期。如果将作用范围修改为singleton,则将Bean放入SpringIOC容器的缓冲池中,并将Bean引用返回给调用者,Spring继续对这些Bean进行后续的生命管理。
Bean的作用域:singleton、prototype、request、session、global session;
singleton:SpringIOC容器中,只会存在一个共享的Bean实例,并且所有对Bean的请求,只要id与该Bean定义匹配,就会返回Bean的同一实例。SpringIOC容器只会创建该Bean定义的唯一实例。这个单一实例会被存储到单例缓存中。Spring中,singleton是指在某一个Spring容器中,存在单一的类实例;GOF(四人帮)模式中,每一个ClassLoader中存在但以实例;
prototype:每次对bean的请求(注入到另一个Bean中或通过程序的方式调用getBean方法)时,都会创建一个新的Bean的实例。根据经验,对有状态的Bean采用prototype,而无状态的采用singleton;
对于prototype作用域的Bean,Spring不能对一个prototypeBean的整个生命周期负责,容器在初始化、配置、装饰或装配完一个prototype实例后,将其交个客户端,之后就不再管该Bean了。不管何种作用域,容器都会在调用所有对象的初始化生命周期回调方法,但是对于prototype来说,任何配置好的析构生命周期回调方法都不会被调用。清除prototype作用域的对象并释放任何该Bean所持有的昂贵资源,都是客户端的工作;
使Spring容器释放被prototype作用域的bean占用资源的一种可行方式为使用Bean的后置处理器,对该处理器所持有的bean引用进行清除。
(13)对于singleton中的bean,当容器关闭,将触发Spring对bean的后续生命周期进行管理,首先如果Bean实现了disposableBean接口,将调用afterPropertiesSet()方法,可以在此编写释放资源、记录日志的代码;
(14)对于singleton中的bean,如果通过<bean>的destory-method属性指定的Bean的销毁方法,Spring将执行Bean的这个方法,完成Bean资源的释放等操作;