Spring是我们经常使用的一个框架,它功能之一是提供了我们管理bean对象的手段,而且它提供了很多钩子方法给我们使用。什么是钩子方法呢?钩子方法就是:在bean的生命周期之中,经历了一系列的过程之中,Spring留给我们的一个后门,让我们能在Spring的生命周期之中执行我们想要的方法,从而实现我们想要的功能。接下来我们介绍一下生命周期,然后一个一个介绍我见过的样例或者我自己写的样例。
Spring生命周期的各种Aware
Spring的生命周期(我们撇开网络上很多资料,因为我觉得网络上很多资料要么不全,要么分不清context和beanFactory,然后将context的一些过程归入beanFactory之中。我这里只看Spring官方文档,我看的是5.3.0-SNAPSHOT版本的。)
上面列表说的114个初始化方法,13个销毁方法。这就是我说的钩子方法,只要你进程并实现了对应的方法,spring就会帮我们调用这些方法。
然后针对上面的bean lifecycle 我这里用一个简单的例子给大家演示一下:
<span style="color:#000000"><code class="language-java"><span style="color:#6679cc">public</span> <span style="color:#6679cc">class</span> BeanLifecycle <span style="color:#6679cc">implements</span> BeanNameAware<span style="color:#999999">,</span> BeanClassLoaderAware<span style="color:#999999">,</span> BeanFactoryAware<span style="color:#999999">,</span> EnvironmentAware<span style="color:#999999">,</span>
EmbeddedValueResolverAware<span style="color:#999999">,</span> ResourceLoaderAware<span style="color:#999999">,</span> ApplicationEventPublisherAware<span style="color:#999999">,</span> MessageSourceAware<span style="color:#999999">,</span>
ApplicationContextAware<span style="color:#999999">,</span> ServletContextAware<span style="color:#999999">,</span> BeanPostProcessor<span style="color:#999999">,</span> InitializingBean<span style="color:#999999">,</span> DestructionAwareBeanPostProcessor<span style="color:#999999">,</span>
DisposableBean<span style="color:#999999">{</span>
<span style="color:#6b7394">/**
* BeanNameAware 的 setBeanName,这个是第一个触发
*/</span>
<span style="color:#999999">@Override</span>
<span style="color:#6679cc">public</span> <span style="color:#6679cc">void</span> <span style="color:#3d8fd1">setBeanName</span><span style="color:#999999">(</span>String s<span style="color:#999999">)</span> <span style="color:#999999">{</span>
System<span style="color:#999999">.</span>out<span style="color:#999999">.</span><span style="color:#3d8fd1">println</span><span style="color:#999999">(</span><span style="color:#ac9739">"第一个执行 bean name = "</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#6b7394">/**
* BeanClassLoaderAware 的 setBeanClassLoader
*/</span>
<span style="color:#999999">@Override</span>
<span style="color:#6679cc">public</span> <span style="color:#6679cc">void</span> <span style="color:#3d8fd1">setBeanClassLoader</span><span style="color:#999999">(</span>ClassLoader classLoader<span style="color:#999999">)</span> <span style="color:#999999">{</span>
System<span style="color:#999999">.</span>out<span style="color:#999999">.</span><span style="color:#3d8fd1">println</span><span style="color:#999999">(</span><span style="color:#ac9739">"第二个执行 classLoader = "</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#6b7394">/**
* BeanFactoryAware 的 setBeanFactory
*/</span>
<span style="color:#999999">@Override</span>
<span style="color:#6679cc">public</span> <span style="color:#6679cc">void</span> <span style="color:#3d8fd1">setBeanFactory</span><span style="color:#999999">(</span>BeanFactory beanFactory<span style="color:#999999">)</span> <span style="color:#6679cc">throws</span> BeansException <span style="color:#999999">{</span>
System<span style="color:#999999">.</span>out<span style="color:#999999">.</span><span style="color:#3d8fd1">println</span><span style="color:#999999">(</span><span style="color:#ac9739">"第三个执行 beanFactory = "</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#6b7394">/**
* EnvironmentAware 的 setEnvironment
*/</span>
<span style="color:#999999">@Override</span>
<span style="color:#6679cc">public</span> <span style="color:#6679cc">void</span> <span style="color:#3d8fd1">setEnvironment</span><span style="color:#999999">(</span>Environment environment<span style="color:#999999">)</span> <span style="color:#999999">{</span>
System<span style="color:#999999">.</span>out<span style="color:#999999">.</span><span style="color:#3d8fd1">println</span><span style="color:#999999">(</span><span style="color:#ac9739">"第四个执行 environment = "</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#6b7394">/**
* EmbeddedValueResolverAware 的 EmbeddedValueResolverAware
*/</span>
<span style="color:#999999">@Override</span>
<span style="color:#6679cc">public</span> <span style="color:#6679cc">void</span> <span style="color:#3d8fd1">setEmbeddedValueResolver</span><span style="color:#999999">(</span>StringValueResolver resolver<span style="color:#999999">)</span> <span style="color:#999999">{</span>
System<span style="color:#999999">.</span>out<span style="color:#999999">.</span><span style="color:#3d8fd1">println</span><span style="color:#999999">(</span><span style="color:#ac9739">"第五个执行 resolver = "</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#6b7394">/**
* ResourceLoaderAware 的 setResourceLoader
*/</span>
<span style="color:#999999">@Override</span>
<span style="color:#6679cc">public</span> <span style="color:#6679cc">void</span> <span style="color:#3d8fd1">setResourceLoader</span><span style="color:#999999">(</span>ResourceLoader resourceLoader<span style="color:#999999">)</span> <span style="color:#999999">{</span>
System<span style="color:#999999">.</span>out<span style="color:#999999">.</span><span style="color:#3d8fd1">println</span><span style="color:#999999">(</span><span style="color:#ac9739">"第六个执行 resourceLoader = "</span> <span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#6b7394">/**
* ApplicationEventPublisherAware 的 setApplicationEventPublisher
*/</span>
<span style="color:#999999">@Override</span>
<span style="color:#6679cc">public</span> <span style="color:#6679cc">void</span> <span style="color:#3d8fd1">setApplicationEventPublisher</span><span style="color:#999999">(</span>ApplicationEventPublisher applicationEventPublisher<span style="color:#999999">)</span> <span style="color:#999999">{</span>
System<span style="color:#999999">.</span>out<span style="color:#999999">.</span><span style="color:#3d8fd1">println</span><span style="color:#999999">(</span><span style="color:#ac9739">"第七个执行 applicationEventPublisher = "</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#6b7394">/**
* MessageSourceAware 的 setMessageSource
*/</span>
<span style="color:#999999">@Override</span>
<span style="color:#6679cc">public</span> <span style="color:#6679cc">void</span> <span style="color:#3d8fd1">setMessageSource</span><span style="color:#999999">(</span>MessageSource messageSource<span style="color:#999999">)</span> <span style="color:#999999">{</span>
System<span style="color:#999999">.</span>out<span style="color:#999999">.</span><span style="color:#3d8fd1">println</span><span style="color:#999999">(</span><span style="color:#ac9739">"第八个执行 messageSource = "</span> <span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#6b7394">/**
* ApplicationContextAware 的 setApplicationContext
*/</span>
<span style="color:#999999">@Override</span>
<span style="color:#6679cc">public</span> <span style="color:#6679cc">void</span> <span style="color:#3d8fd1">setApplicationContext</span><span style="color:#999999">(</span>ApplicationContext applicationContext<span style="color:#999999">)</span> <span style="color:#6679cc">throws</span> BeansException <span style="color:#999999">{</span>
System<span style="color:#999999">.</span>out<span style="color:#999999">.</span><span style="color:#3d8fd1">println</span><span style="color:#999999">(</span><span style="color:#ac9739">"第九个执行 applicationContext = "</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#6b7394">/**
* ServletContextAware 的 setServletContext
*/</span>
<span style="color:#999999">@Override</span>
<span style="color:#6679cc">public</span> <span style="color:#6679cc">void</span> <span style="color:#3d8fd1">setServletContext</span><span style="color:#999999">(</span>ServletContext servletContext<span style="color:#999999">)</span> <span style="color:#999999">{</span>
System<span style="color:#999999">.</span>out<span style="color:#999999">.</span><span style="color:#3d8fd1">println</span><span style="color:#999999">(</span><span style="color:#ac9739">"第十个执行 servletContext = "</span> <span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#6b7394">/**
* BeanPostProcessor 的 postProcessBeforeInitialization
*/</span>
<span style="color:#999999">@Override</span>
<span style="color:#6679cc">public</span> Object <span style="color:#3d8fd1">postProcessBeforeInitialization</span><span style="color:#999999">(</span>Object bean<span style="color:#999999">,</span> String beanName<span style="color:#999999">)</span> <span style="color:#6679cc">throws</span> BeansException <span style="color:#999999">{</span>
System<span style="color:#999999">.</span>out<span style="color:#999999">.</span><span style="color:#3d8fd1">println</span><span style="color:#999999">(</span><span style="color:#ac9739">"第十一个执行 postProcessBeforeInitialization bean = "</span> <span style="color:#999999">)</span><span style="color:#999999">;</span>
System<span style="color:#999999">.</span>out<span style="color:#999999">.</span><span style="color:#3d8fd1">println</span><span style="color:#999999">(</span><span style="color:#ac9739">"第十一个执行 postProcessBeforeInitialization beanName = "</span> <span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#6679cc">return</span> bean<span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#6b7394">/**
* InitializingBean 的 afterPropertiesSet
*/</span>
<span style="color:#999999">@Override</span>
<span style="color:#6679cc">public</span> <span style="color:#6679cc">void</span> <span style="color:#3d8fd1">afterPropertiesSet</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#6679cc">throws</span> Exception <span style="color:#999999">{</span>
System<span style="color:#999999">.</span>out<span style="color:#999999">.</span><span style="color:#3d8fd1">println</span><span style="color:#999999">(</span><span style="color:#ac9739">"第十二个执行 = afterPropertiesSet"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#6b7394">/**
* 指定 的 initMethod
*/</span>
<span style="color:#6679cc">public</span> <span style="color:#6679cc">void</span> <span style="color:#3d8fd1">initMethod</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#999999">{</span>
System<span style="color:#999999">.</span>out<span style="color:#999999">.</span><span style="color:#3d8fd1">println</span><span style="color:#999999">(</span><span style="color:#ac9739">"第十三个执行 = initMethod"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#6b7394">/**
* BeanPostProcessor 的 postProcessAfterInitialization
*/</span>
<span style="color:#999999">@Override</span>
<span style="color:#6679cc">public</span> Object <span style="color:#3d8fd1">postProcessAfterInitialization</span><span style="color:#999999">(</span>Object bean<span style="color:#999999">,</span> String beanName<span style="color:#999999">)</span> <span style="color:#6679cc">throws</span> BeansException <span style="color:#999999">{</span>
System<span style="color:#999999">.</span>out<span style="color:#999999">.</span><span style="color:#3d8fd1">println</span><span style="color:#999999">(</span><span style="color:#ac9739">"第十四个执行 postProcessAfterInitialization bean = "</span> <span style="color:#999999">)</span><span style="color:#999999">;</span>
System<span style="color:#999999">.</span>out<span style="color:#999999">.</span><span style="color:#3d8fd1">println</span><span style="color:#999999">(</span><span style="color:#ac9739">"第十四个执行 postProcessAfterInitialization beanName = "</span> <span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#6679cc">return</span> bean<span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#6b7394">/**
* DestructionAwareBeanPostProcessor 的 postProcessBeforeDestruction
*/</span>
<span style="color:#999999">@Override</span>
<span style="color:#6679cc">public</span> <span style="color:#6679cc">void</span> <span style="color:#3d8fd1">postProcessBeforeDestruction</span><span style="color:#999999">(</span>Object o<span style="color:#999999">,</span> String s<span style="color:#999999">)</span> <span style="color:#6679cc">throws</span> BeansException <span style="color:#999999">{</span>
System<span style="color:#999999">.</span>out<span style="color:#999999">.</span><span style="color:#3d8fd1">println</span><span style="color:#999999">(</span><span style="color:#ac9739">"第一个执行的销毁方法 o = "</span> <span style="color:#999999">)</span><span style="color:#999999">;</span>
System<span style="color:#999999">.</span>out<span style="color:#999999">.</span><span style="color:#3d8fd1">println</span><span style="color:#999999">(</span><span style="color:#ac9739">"第一个执行的销毁方法 s = "</span> <span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#6b7394">/**
* DisposableBean 的 destroy
*/</span>
<span style="color:#999999">@Override</span>
<span style="color:#6679cc">public</span> <span style="color:#6679cc">void</span> <span style="color:#3d8fd1">destroy</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#6679cc">throws</span> Exception <span style="color:#999999">{</span>
System<span style="color:#999999">.</span>out<span style="color:#999999">.</span><span style="color:#3d8fd1">println</span><span style="color:#999999">(</span><span style="color:#ac9739">"第二个执行的销毁方法 = destroy"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#6679cc">public</span> <span style="color:#6679cc">void</span> <span style="color:#3d8fd1">destroyMethod</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#999999">{</span>
System<span style="color:#999999">.</span>out<span style="color:#999999">.</span><span style="color:#3d8fd1">println</span><span style="color:#999999">(</span><span style="color:#ac9739">"第三个执行的销毁方法 "</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#999999">}</span>
</code></span>
然后我创建了下面一个测试用例:
<span style="color:#000000"><code class="language-java"><span style="color:#999999">@SpringBootApplication</span>
<span style="color:#6679cc">public</span> <span style="color:#6679cc">class</span> LifecycleMain <span style="color:#999999">{</span>
<span style="color:#999999">@Bean</span><span style="color:#999999">(</span>initMethod <span style="color:#ac9739">=</span> <span style="color:#ac9739">"initMethod"</span><span style="color:#999999">,</span> destroyMethod <span style="color:#ac9739">=</span> <span style="color:#ac9739">"destroyMethod"</span><span style="color:#999999">)</span>
<span style="color:#6679cc">public</span> BeanLifecycle <span style="color:#3d8fd1">beanLifecycle</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#999999">{</span>
<span style="color:#6679cc">return</span> <span style="color:#6679cc">new</span> BeanLifecycle<span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#999999">@Bean</span><span style="color:#999999">(</span>initMethod <span style="color:#ac9739">=</span> <span style="color:#ac9739">"initMethod"</span><span style="color:#999999">,</span> destroyMethod <span style="color:#ac9739">=</span> <span style="color:#ac9739">"destroyMethod"</span><span style="color:#999999">)</span>
<span style="color:#6679cc">public</span> BeanLifecycle <span style="color:#3d8fd1">beanLifecycle2</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#999999">{</span>
<span style="color:#6679cc">return</span> <span style="color:#6679cc">new</span> BeanLifecycle<span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#6679cc">public</span> <span style="color:#6679cc">static</span> <span style="color:#6679cc">void</span> <span style="color:#3d8fd1">main</span><span style="color:#999999">(</span>String<span style="color:#999999">[</span><span style="color:#999999">]</span> args<span style="color:#999999">)</span> <span style="color:#999999">{</span>
ConfigurableApplicationContext context <span style="color:#ac9739">=</span> <span style="color:#6679cc">new</span> SpringApplication<span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#3d8fd1">run</span><span style="color:#999999">(</span>LifecycleMain<span style="color:#999999">.</span><span style="color:#6679cc">class</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
context<span style="color:#999999">.</span><span style="color:#3d8fd1">close</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#6b7394">//这个方法用来触发destroy-method</span>
<span style="color:#999999">}</span>
<span style="color:#999999">}</span>
</code></span>
output如下:
<span style="color:#000000"><code>第一个执行 bean name =
第二个执行 classLoader =
第三个执行 beanFactory =
第四个执行 environment =
第五个执行 resolver =
第六个执行 resourceLoader =
第七个执行 applicationEventPublisher =
第八个执行 messageSource =
第九个执行 applicationContext =
第十二个执行 = afterPropertiesSet
第十三个执行 = initMethod
第一个执行 bean name =
第二个执行 classLoader =
第三个执行 beanFactory =
第四个执行 environment =
第五个执行 resolver =
第六个执行 resourceLoader =
第七个执行 applicationEventPublisher =
第八个执行 messageSource =
第九个执行 applicationContext =
第十二个执行 = afterPropertiesSet
第十三个执行 = initMethod
第十一个执行 bean =
第十一个执行 beanName =
第十一个执行 bean =
第十一个执行 beanName =
第十四个执行 bean =
第十四个执行 beanName =
第十四个执行 bean =
第十四个执行 beanName =
第二个执行的销毁方法 = destroy
第三个执行的销毁方法
第二个执行的销毁方法 = destroy
第三个执行的销毁方法
</code></span>
这里我把后面输出的对象都去掉了,因为输出结果太长影响我们观看。
然后我先简单说说Aware,Aware英文翻译是知道的意思,Aware接口作用就是其实就是 你想知道什么信息,然后就实现什么样的Aware,Spring会通过setXXX方法,将你想要知道的信息通过参数传递给你。
所以 BeanNameAware, BeanClassLoaderAware, BeanFactoryAware……的作用就是给对应的Bean回设这个Bean想知道的信息。
而这里的有个小疑问:为什么第十个执行的Bean没执行呢?而想象之中第十一个执行的方法在第十三个方法之后执行呢?
第一个问题是我们没有对应的Servlet。
第二个问题:其实BeanPostProcessor是一个对所有Bean都会拦截的方法,如果我们想要在这个bean之前执行,我们需要在context的refresh阶段之前添加进去而不是通过bean注册进去,我们通过另外一种方式试试。
<span style="color:#000000"><code class="language-java"><span style="color:#6679cc">public</span> <span style="color:#6679cc">static</span> <span style="color:#6679cc">void</span> <span style="color:#3d8fd1">main</span><span style="color:#999999">(</span>String<span style="color:#999999">[</span><span style="color:#999999">]</span> args<span style="color:#999999">)</span> <span style="color:#999999">{</span>
AnnotationConfigApplicationContext context <span style="color:#ac9739">=</span> <span style="color:#6679cc">new</span> AnnotationConfigApplicationContext<span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
context<span style="color:#999999">.</span><span style="color:#3d8fd1">getBeanFactory</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#3d8fd1">addBeanPostProcessor</span><span style="color:#999999">(</span><span style="color:#6679cc">new</span> BeanLifecycle<span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
context<span style="color:#999999">.</span><span style="color:#3d8fd1">register</span><span style="color:#999999">(</span>BeanLifecycle<span style="color:#999999">.</span><span style="color:#6679cc">class</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
context<span style="color:#999999">.</span><span style="color:#3d8fd1">refresh</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
context<span style="color:#999999">.</span><span style="color:#3d8fd1">getBean</span><span style="color:#999999">(</span>BeanLifecycle<span style="color:#999999">.</span><span style="color:#6679cc">class</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
</code></span>
output如下:
<span style="color:#000000"><code>22:34:48.200 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
第十一个执行 postProcessBeforeInitialization bean =
第十一个执行 postProcessBeforeInitialization beanName =
第十四个执行 postProcessAfterInitialization bean =
第十四个执行 postProcessAfterInitialization beanName =
22:34:48.227 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
第十一个执行 postProcessBeforeInitialization bean =
第十一个执行 postProcessBeforeInitialization beanName =
第十四个执行 postProcessAfterInitialization bean =
第十四个执行 postProcessAfterInitialization beanName =
22:34:48.229 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
第十一个执行 postProcessBeforeInitialization bean =
第十一个执行 postProcessBeforeInitialization beanName =
第十四个执行 postProcessAfterInitialization bean =
第十四个执行 postProcessAfterInitialization beanName =
22:34:48.230 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
第十一个执行 postProcessBeforeInitialization bean =
第十一个执行 postProcessBeforeInitialization beanName =
第十四个执行 postProcessAfterInitialization bean =
第十四个执行 postProcessAfterInitialization beanName =
22:34:48.232 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
第十一个执行 postProcessBeforeInitialization bean =
第十一个执行 postProcessBeforeInitialization beanName =
第十四个执行 postProcessAfterInitialization bean =
第十四个执行 postProcessAfterInitialization beanName =
22:34:48.235 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'beanLifecycle'
第一个执行 bean name =
第二个执行 classLoader =
第三个执行 beanFactory =
第十一个执行 postProcessBeforeInitialization bean =
第十一个执行 postProcessBeforeInitialization beanName =
第四个执行 environment =
第五个执行 resolver =
第六个执行 resourceLoader =
第七个执行 applicationEventPublisher =
第八个执行 messageSource =
第九个执行 applicationContext =
第十二个执行 = afterPropertiesSet
第十四个执行 postProcessAfterInitialization bean =
第十四个执行 postProcessAfterInitialization beanName =
</code></span>
为什么上面的postProcessAfterInitialization方法执行了好多次呢?
我们看看 BeanPostProcessor 的postProcessBeforeInitialization
方法的注解:
Apply this BeanPostProcessor to the given new bean instance before any bean initialization callbacks (like InitializingBean’s afterPropertiesSet
or a custom init-method). The bean will already be populated with property values. The returned bean instance may be a wrapper around the original.
大意就是:这个方法会被每个bean 初始化之前都会回调这个方法,比如 会在InitializingBean’s afterPropertiesSet或bean自定义的一个init-method方法调用之前回调这个方法。
然后看看postProcessAfterInitialization
的注解:
Apply this BeanPostProcessor to the given new bean instance after any bean initialization callbacks (like InitializingBean’s afterPropertiesSet or a custom init-method). The bean will already be populated with property values. The returned bean instance may be a wrapper around the original.
大意就是:这个方法会在每个bean初始化之后都会回调这个方法。
这样就解释了为什么的 postProcessBeforeInitialization
和 postProcessAfterInitialization
方法会被打印这么多次,因为它是每个bean被初始化一次,它都会被调用一次。那么我设想是不是在需要对某些 bean,或者是底层接口的一个bean,我想拦截下来并且做一点修饰,这样就不需要入侵到底层代码里面去了。
然后看了下 BeanPostProcessor 的注解:
Factory hook that allows for custom modification of new bean instances — for example, checking for marker interfaces or wrapping beans with proxies.
大意就是:Factory的hook(钩子方法),可以定制修改一个新的bean实例,比如检查interfaces的创建条件对不对,使用代理包装某个beans。
不过上面有个结果比较奇怪:为什么的postProcessBeforeInitialization
会在 EnvironmentAware之前执行。这个挖个坑,后面地细细研究一下。
这里给大家一个我使用BeanPostProcessor的例子。
<span style="color:#000000"><code class="language-java"><span style="color:#999999">@Configuration</span>
<span style="color:#6679cc">public</span> <span style="color:#6679cc">class</span> MysqlConfigAdapter <span style="color:#6679cc">implements</span> BeanPostProcessor<span style="color:#999999">{</span>
<span style="color:#999999">@Value</span><span style="color:#999999">(</span><span style="color:#ac9739">"mysql.username"</span><span style="color:#999999">)</span>
<span style="color:#6679cc">private</span> String username<span style="color:#999999">;</span>
<span style="color:#999999">@Value</span><span style="color:#999999">(</span><span style="color:#ac9739">"mysql.password"</span><span style="color:#999999">)</span>
<span style="color:#6679cc">private</span> String password<span style="color:#999999">;</span>
<span style="color:#999999">@Override</span>
<span style="color:#6679cc">public</span> Object <span style="color:#3d8fd1">postProcessAfterInitialization</span><span style="color:#999999">(</span>Object bean<span style="color:#999999">,</span> String beanName<span style="color:#999999">)</span> <span style="color:#6679cc">throws</span> BeansException <span style="color:#999999">{</span>
<span style="color:#6679cc">if</span> <span style="color:#999999">(</span>bean <span style="color:#6679cc">instanceof</span> XxxDatabase<span style="color:#999999">)</span> <span style="color:#999999">{</span>
<span style="color:#999999">(</span><span style="color:#999999">(</span>XxxDatabase<span style="color:#999999">)</span>bean<span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#3d8fd1">setUsername</span><span style="color:#999999">(</span>username<span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">(</span><span style="color:#999999">(</span>XxxDatabase<span style="color:#999999">)</span>bean<span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#3d8fd1">setPassword</span><span style="color:#999999">(</span>password<span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#6679cc">return</span> bean<span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#999999">@Override</span>
<span style="color:#6679cc">public</span> <span style="color:#6679cc">void</span> <span style="color:#3d8fd1">setApplicationContext</span><span style="color:#999999">(</span>ApplicationContext applicationContext<span style="color:#999999">)</span> <span style="color:#6679cc">throws</span> BeansException <span style="color:#999999">{</span>
<span style="color:#6679cc">this</span><span style="color:#999999">.</span>applicationContext <span style="color:#ac9739">=</span> applicationContext<span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#999999">}</span>
</code></span>
上面的例子是本人在实际生产运用中使用到的例子(改造过),当时是因为使用了第三方中间件,而为了能让第三方中间件接入配置中心(比如阿波罗,nacos),而不侵入对方的代码,就在外层写了个适配器(适配器模式)。拦截下对应的bean,并且修改里面的值,再给出去。恰好符合注解讲的那样:The returned bean instance may be a wrapper around the original.
除了上面的例子之外,我们再说一点BeanPostProcessor的两个注意事项:
- 注册方式:BeanPostProcessor可以直接被ApplicationContext发现,也可以手动通过BeanFactory注册。
- 顺序:有多个BeanPostProcessor的时候,通过ApplicationContext发现的就会看这个bean是否implement了PriorityOrdered和Ordered接口,按照这两个的顺序来排序(PriorityOrdered优先于Ordered)。如果是通过手动注册来的,就会忽略掉这些属性,只看添加的顺序来决定先后顺序。最后@Order是无效的,目前还没有实现(5.3.0-SNAPSHOT)版本。
BeanFactoryPostProcessor
PostProcessor 其实除了这个BeanPostProcessor 之外,之前看源码的时候也注意到了有另外一个:BeanFactoryPostProcessor。然后我们看看BeanFactoryPostProcessor
源码注解解释。
Factory hook that allows for custom modification of an application context’s bean definitions, adapting the bean property values of the context’s underlying bean factory.
大意就是说:这是要给针对BeanFactory的钩子方法,是一个可以对applicationContext的BeanFactory修改的方法。修改这个context的beanfactory的properties value。这个权限非常大。
- 它的注册方式也分两种:通过applicationContext自动探测,通过ConfigurableApplicationContext.addBeanFactoryPostProcessor手动注册。
- 它的顺序性和BeanPostProcessor一样
其实BeanFactoryPostProcessor
是要给非常强大的接口,我们的@Configuration功能,SpringBoot的自动装配还有Spring-Mybatis的适配都是靠这个来实现的。具体的实现可以参考ConfigurationClassPostProcessor
,如果后面有机会,可以再给大家看看ConfigurationClassPostProcessor它的实现。(再挖个坑。)
BeanFactoryPostProcessor 和BeanPostProcessor有个很大的区别是:BeanFactoryPostProcessor 的执行时机很早,在所有的bean初始化包括那些aware赋值之前就执行了,而BeanPostProcessor是每个bean初始化之前执行postProcessBeforeInitialization,初始化之后执行postProcessAfterInitialization。
好了,这期就到这里了。
那么我们把各种各样的Aware看做一个阶段,我们是否可以得出这样的结论:
<span style="color:#000000"><code>BeanFactoryPostProcessor.postProcessBeanFactory -->
Aware -->
BeanPostProcessor.postProcessBeforeInitialization -->
initialBean -->
initMethod -->
BeanPostProcessor.postProcessAfterInitialization -->
DisposableBean -->
destroyMethod</code></span>