在很多技术中,都有生命周期这个概念,如在Android中,有Activity、Fragment等的生命周期;在Web容器中,有Servlet的生命周期。想要成为高级开发者,就必须要深入理解其生命周期。同样的,在Spring容器中的Bean也有一系列的生命周期,要掌握好Spring,就要先掌握Spring中Bean的生命周期。
在Spring中,可以从两个层面定义Bean的生命周期:一是Bean的作用范围,二是Spring实例化Bean时所经历的一系列阶段。下面分别对BeanFactory和ApplicationContext中Bean的生命周期进行分析。
根据图示的生命周期,具体过程如下:
(1)当调用者调用getBean(beanName)向容器请求某一个Bean时,如果容器注册了InstantiationAwareBeanPostProcessor接口,则在实例化Bean之前,将调用接口的postProcessBeforeInstantiation()方法。
(2)根据配置情况调用Bean的构造函数或工厂方法实例化Bean。
(3)如果容器注册了InstantiationAwareBeanPostProcessor接口,在实例化Bean之后,调用该接口的postProcessBeforeInstantiation()方法,对实例化的对象进行一些初始化设置。
(4)如果Bean 配置了属性信息,那么容器在这一步将配置的属性设置到Bean对应的属性中,在设置属性之前将先调用InstantiationAwareBeanPostProcessor接口的postProcessPropertyValues()方法。
(5)调用Bean中的setXxx()方法设置属性。
(6)如果Bean实现了BeanNameAware接口,则会调用该接口的setBeanName()方法,将配置文件中该Bean对应的名称设置到Bean中。
(7)如果Bean实现了BeanFactoryAware接口,则会调用该接口的setBeanFactory()方法,将BeanFactory容器实例设置到Bean中。
(8)如果BeanFactory装配了BeanPostProcessor后处理器,则将调用BeanPostProcessor接口的Object postProcessBeforeInitialization方法对Bean进行加工操作。其中,传入的bean是当前正在处理的bean,而beanName是当前Bean在配置文件中的配置名,返回加工处理后的bean。用户可以使用该方法对某些Bean进行特殊的处理。Spring容器所提供的AOP、动态代理等功能都通过BeanPostProcessor实现。
(9)如果Bean实现了InitializingBean接口,则将调用该接口的afterPropertiesSet()方法。
(10)如果在配置文件的bean标签中通过init-method属性指定了初始化方法,则会执行这个方法。
(11)如果BeanFactory装配了BeanPostProcessor后处理器,在这里则会执行Object postProcessAfterInitialization()方法对Bean进行加工处理。
BeanPostProcessor后处理器定义了两个方法,分别是postProcessBeforeInitialization()和postProcessAfterInitialization(),分别在第8步和在此处调用。
(12)如果在配置文件中指定了bean的scope=”prototype”,意味着配置的这个bean是多例的,每次获取该bean都会返回一个新实例化的bean,所以在这一步之后Spring容器不再管理多例的Bean,直接将当前生成的实例返回给用户。
对于scope=”singleton”的Bean(默认情况),意味着这个Bean是单例的,就需要把这个Bean缓存到在Spring IOC容器中,用户每次获取时都从这个容器中获取,并且Spring会对这些Bean进行后续的生命周期管理。
(13)对于单例的Bean,容器关闭时,会触发Spring对Bean的后续生命周期的管理工作。如果Bean实现了DisposableBean接口,则会调用该接口的destroy()方法,在这里可以进行释放资源、记录日志等操作。
(14)对于单例的Bean,如果在配置文件中指定了destroy-method属性,Spring则会执行这个属性配置的方法,完成Bean资源释放等操作。
以上生命周期所经历的方法可大致分为以下四类:
a、Bean自身的方法
包括实例化Bean时Bean的构造方法,设置属性值时Bean的set方法,以及通过配置文件配置的init-method和destroy-method指定的方法。
b、Bean级生命周期接口方法
包括BeanNameAware、BeanFactoryAware、InitializingBean和DisposableBean,这些接口方法由Bean直接实现。
c、容器级生命周期接口方法
包括InstantiationAwareBeanPostProcessor和BeanPostProcessor两个接口。一般称他们的实现类为后处理器,后处理器接口一般不由Bean本身实现,他们独立于Bean,实现类以容器附加装置的形式注册到Spring容器中,并通过接口反射为Spring容器扫描识别。当Spring容器创建任何Bean时,这些后处理器都会起作用,这些后处理器的影响是全局性的。
d、工厂后处理器接口方法
包括AspectJWeavingEnabler、CustomAutowireConfigurer、ConfigurationClassPostProcessor等类,都实现了BeanFactoryPostProcessor接口。工厂后处理器也是容器级的,在应用上下文装配配置文件后立即调用。
Spring容器中还可以注册多个后处理器,只要他们都实现了Ordered接口,Spring容器就会按照特定的顺序依次调用这些后处理器。
具体过程与上述BeanFactory中Bean的生命周期类似,这里不再详解。
在IDEA中查看ApplicationContext的继承关系图:
可以看到,ApplicationContext继承了BeanFactory,BeanFactory是Spring中比较原始的Factory,它不支持AOP、Web等Spring插件,而ApplicationContext不仅包含了BeanFactory的所有功能,还支持Spring的各种插件,还以一种面向框架的方式工作以及对上下文进行分层和实现继承。
BeanFactory是Spring框架的基础设施,面向Spring本身;而ApplicationContext面向使用Spring的开发者,相比BeanFactory提供了更多面向实际应用的功能,几乎所有场合都可以直接使用ApplicationContext而不是底层的BeanFactory。