疯狂的小鸡

Spring中的bean

字数统计: 1.4k阅读时长: 5 min
2018/10/05 Share

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接口,则会首先对postProcessBeforeDestruction方法进行调用,再调用该接口的destroy()方法,在这里可以进行释放资源、记录日志等操作。如果在配置文件中指定了destroy-method属性,Spring则会在最后执行这个属性配置的方法,完成Bean资源释放等操作。

BeanPostProcessor

BeanPostProcessor是Spring中定义的一个接口,如果我们想在Spring容器中完成bean实例化、配置以及其他初始化方法前后要添加一些自己逻辑处理。我们需要定义一个或多个BeanPostProcessor接口实现类,然后注册到Spring IoC容器中。
它有两个接口方法,postProcessorBeforeInitailization 和postProcessorAfterInitailization具体发生在doCreateBean方法中populateBean方法之后的initializeBean方法中。两者包围invokeInitMethids方法。如果该bean是实现了InitializingBean接口,并且同时在配置文件中指定了init-method,系统则是先调用afterPropertiesSet方法,然后在调用init-method中指定的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}

if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

Bean的依赖检查

当Bean之间依赖关系复杂时,依赖注入不一定能一次成功。通过在Bean定义中指定dependency-check属性可以设置依赖检查,有4种模式:
none(默认,不检查)
simple(只检查基本数据类型)
object(只检查对象类型)
all(全检查)

FactoryBean

在某些情况下,实例化bean过程比较复杂,如果按照传统的方式,则需要在中提供大量的配置信息,配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个 FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化bean的逻辑。
在该接口中定义了以下3个方法。

#T getObject():返回由FactoryBean创建的bean实例,如果isSingleton()返回true,则该实例会放到Spring容器中单实例缓存池中。

#boolean isSingleton():返回由FactoryBean创建的bean实例的作用域是singleton还是prototype。

#Class getObjectType():返回FactoryBean创建的bean类型。

当配置文件中的class属性配置的实现类是FactoryBean时,通过 getBean()方法返回的不是FactoryBean本身,而是FactoryBean#getObject()方法所返回的对象,相当于FactoryBean#getObject()代理了getBean()方法。若想获得FactoryBean本身,则需在bean前面加一个转义符&。
FactoryBean一例:https://www.cnblogs.com/davidwang456/p/3688250.html

Bean对容器的感知

Spring中提供一些Aware结尾相关接口,像是BeanFactoryAware、 BeanNameAware、ApplicationContextAware、ResourceLoaderAware、ServletContextAware等等。
在设置Bean的属性之后,调用初始化回调方法之前,Spring会调用aware接口的setter方法。

CATALOG
  1. 1. Bean的生命周期
  2. 2. BeanPostProcessor
  3. 3. Bean的依赖检查
  4. 4. FactoryBean
  5. 5. Bean对容器的感知