IOC中的扩展点 Spring在初始化容器的过程中,提供了一些扩展点,可以让用户添加一些自定义的操作来处理Bean。
这里先贴出ioc创建过程的主要流程代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 public void refresh () throws BeansException, IllegalStateException { synchronized (this .startupShutdownMonitor) { prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory); try { postProcessBeanFactory(beanFactory); invokeBeanFactoryPostProcessors(beanFactory); registerBeanPostProcessors(beanFactory); initMessageSource(); initApplicationEventMulticaster(); onRefresh(); registerListeners(); finishBeanFactoryInitialization(beanFactory); finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } destroyBeans(); cancelRefresh(ex); throw ex; } finally { resetCommonCaches(); } } }
常用的扩展点有:
在构建BeanFactory的时候,有BeanFactoryPostProcessor
在构建Bean的时候,有BeanPostProcessor
在创建和销毁Bean的时候有InitializingBean(在BPP的调用栈附近)和DisposableBean
IOC Bean的扩展点,也是体现Bean生命周期的一部分, Bean的生命周期如图:
BeanFactoryPostProcessor 1 2 3 public interface BeanFactoryPostProcessor { void postProcessBeanFactory (ConfigurableListableBeanFactory beanFactory) throws BeansException ; }
可以看到这个接口需要实现postProcessBeanFactory
, 然后可以通过参数beanFacory
来操作,实现该接口,可以在spring的bean创建之前,修改bean的定义属性(这个阶段其实就是修改beandefinitiaon
)。也就是说,Spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据,并可以根据需要进行修改,例如可以把bean的scope
从singleton
改为prototype
,也可以把property的值给修改掉。可以同时配置多个BeanFactoryPostProcessor,并通过设置order
属性来控制各个BeanFactoryPostProcessor的执行次序。
ioc加载过程中(refresh
方法),真正调用BeanFactoryPostProcessor
的方法是invokeBeanFactoryPostProcessors
BeanPostProcessor 如果我们需要在Spring容器完成Bean的实例化、配置和其他的初始化前后添加一些自己的逻辑处理,我们就可以定义一个或者多个BeanPostProcessor
接口的实现,然后注册到容器中。它是针对已经初始化的 beans 进行的回调,也就是说是对实例化好以后的 beans 进行的回调
接口定义如下:
1 2 3 4 5 6 7 8 9 10 public interface BeanPostProcessor { Object postProcessBeforeInitialization (Object bean, String beanName) throws BeansException; Object postProcessAfterInitialization (Object bean, String beanName) throws BeansException; }
BeanPostProcessor
的注册是在Ioc的加载过程中的registerBeanPostProcessors()
,该过程中会实例化所有的BPP,并根据优先级排序。调用BPP的逻辑是在初始化所有的Bean之后
调用过程是:
1 2 3 4 5 finishBeanFactoryInitialization->preInstantiateSingletons -> getBean -> doGetBean -> createBean -> doCreateBean -> initializeBean
initializeBean
里执行具体的回调(BeanPostProcessorsBeforeInitialization
,afterPropertiesSet
,BeanPostProcessorsAfterInitialization
), 代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null ) { AccessController.doPrivileged((PrivilegedAction<Object >) () -> { invokeAwareMethods(beanName, bean); return null ; }, getAccessControlContext()) ; } else { // 如果 bean 实现了 BeanNameAware 、BeanClassLoaderAware 或 BeanFactoryAware 接口,回调 invokeAwareMethods (beanName, bean) ; } Object wrappedBean = bean ; if (mbd == null || !mbd.isSynthetic()) { // 回调 BeanPostProcessor 的 postProcessBeforeInitialization wrappedBean = applyBeanPostProcessorsBeforeInitialization (wrappedBean, beanName) ; } try { // 处理 bean 中定义的 init-method , // 或者如果 bean 实现了 InitializingBean 接口,调用 afterPropertiesSet () 方法 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()) { // 回调 BeanPostProcessor 的 postProcessAfterInitialization wrappedBean = applyBeanPostProcessorsAfterInitialization (wrappedBean, beanName) ; } return wrappedBean ; }
这个过程中可以看到,最后执行的回调方法不止有BeanFactoryPostProcessor
接口的, 还有实现InitializingBean
的,如:
1 2 3 public interface InitializingBean { void afterPropertiesSet () throws Exception ; }