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的两个注意事项:

  1. 注册方式:BeanPostProcessor可以直接被ApplicationContext发现,也可以手动通过BeanFactory注册。
  2. 顺序:有多个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。这个权限非常大。

  1. 它的注册方式也分两种:通过applicationContext自动探测,通过ConfigurableApplicationContext.addBeanFactoryPostProcessor手动注册。
  2. 它的顺序性和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>

spring 强大的钩子函数总结相关推荐

  1. java钩子函数(hook)以spring源码为例

    一.什么是钩子函数 请问在Spring中,如果JVM异常终止,Spring是如何保证会释放掉占用的资源,比如说数据库连接等资源呢?钩子函数非常简单,简单到只用摘抄一段Spring代码即可. 二.问题 ...

  2. 用Delphi实现Windows的鼠标钩子函数

    用Delphi实现Windows的鼠标钩子函数 Delphi是基于PASCAL语言的Windows编程工具,功能十分强大.然而在Delphi的帮助 文件中,对Windows API函数的说明沿袭了 V ...

  3. Vue钩子函数mounted实现进入页面立即查询的功能案例

    Vue的钩子函数:当执行到某一阶段就会执行的方法/函数.就相当于spring中bean的生命周期一样.

  4. C语言 - 钩子函数详解

    自学到线程池 被各种函数指针的套娃操作套蒙了, 所以写一篇来总结一下. 首先要搞清楚几个事情 函数指针和指针函数 函数指针是指针,可以指向任一"同类型"的函数 指针函数是函数,这个 ...

  5. k8s pod生命周期、初始化容器、钩子函数、容器探测、重启策略

    pod结构 Pause容器 Pause容器是每个Pod都会有的一个根容器,它的作用有两个 可以以它为根据,评估整个pod的健康状态 可以在根容器上设置IP地址,其他容器都以此IP(Pod IP),以实 ...

  6. VUE 钩子函数超详细解析

    点击上方蓝色字体关注我吧 一起学习,一起进步,做积极的人! 前言 Vue 实例在被创建时,会经过一系列的初始化过程,初始化过程中会运行一些函数,叫做生命周期钩子函数,通过运用钩子函数,用户在可以在Vu ...

  7. WIN32汇编: 24.WINDOWS钩子函数

    第二十四课 WINDOWS钩子函数 本课中我们将要学习WINDOWS钩子函数的使用方法.WINDOWS钩子函数的功能非常强大,有了它您可以探测其它进程并且改变其它进程的行为. 理论: WINDOWS的 ...

  8. Vue2.0 探索之路——生命周期和钩子函数的一些理解

    前言 在使用vue一个多礼拜后,感觉现在还停留在初级阶段,虽然知道怎么和后端做数据交互,但是对于mounted这个挂载还不是很清楚的.放大之,对vue的生命周期不甚了解.只知道简单的使用,而不知道为什 ...

  9. 使用钩子函数[4] - 钩子链和 CallNextHookEx 的返回值

    SetWindowsHookEx 函数的第一个参数表示钩子类型, 共有 14 种选择, 前面我们已经用过两种: WH_KEYBOARD.WH_MOUSE. 系统会为每一种类型的钩子建立一个表(那就是 ...

最新文章

  1. RapidFramework使用Oracle的步骤
  2. Android API Guides 安卓API指导----第一部分:Introduction(介绍)
  3. PHP设置块注释的模板
  4. java去除json 转移,Spring MVC返回的json去除根节点名称的方法
  5. [CQOI2012]交换棋子【网络流】【费用流】
  6. 物联网在改造海上钻井平台监测方面发挥着关键作用
  7. 登录超时服务器未响应,怎样解决超时时间已到、在操作完成之前超时时间已过或服务器未响应的问题?...
  8. 公众号回复单个图文消息
  9. QA:Visual C# 2008 compiler could not be created.
  10. 关于x64dbg里面的Assemble
  11. 最新破解无线网络破解教程,一键破解wpa/wpa2密码软件下载。破解不用抓包不用跑字典。快速破解wpa/wpa2密码...
  12. 【python实战】23个爬虫项目源码:微信、淘宝、知乎、微博...
  13. Python数据库编程
  14. 软件开发流程:软件运维流程
  15. Linux中各种 command not found问题解决
  16. 【无标题】HTMLCSS学习总结
  17. 国家知识产权局宣告易百珑自发电专利权有效
  18. 计算机辅助设计技术领域的应用,关于计算机辅助设计技术在规划设计中的应用...
  19. 这有300+门刚刚开课的编程计算机科学免费课程大集合
  20. 蓝牙规范-Vol 6:低功耗控制器 Part A 物理层规范

热门文章

  1. 工业设计公司的办公环境有哪些特点?
  2. prctl()函数应用
  3. python 同花顺thstrader_GitHub - hooddonkey/THSTrader: 量化交易。最新版通用版同花顺客户端的python API。(Python3)...
  4. Dell服务器RAID卡介绍及监控
  5. 微软GitHub旗帜鲜明抵制996!
  6. oak深度相机入门教程-创建自定义模型
  7. 铅卤化物钙钛矿ABX3晶体薄膜量子点
  8. Redis数据结构之hash
  9. day19总结和作业
  10. 佐客牛排机器人餐厅_这些机器人服务员上菜的网红餐厅你一定喜欢丨打卡指南...