spring 强大的钩子函数总结

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>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Spring Boot中,也有一些钩子函数可以用于扩展和定制应用程序的行为。 1. ApplicationRunner和CommandLineRunner ApplicationRunner和CommandLineRunner都是用于在Spring Boot应用程序启动后执行某些操作的接口。它们的区别在于ApplicationRunner接受一个ApplicationArguments参数,可以获取命令行参数,而CommandLineRunner只接受一个String数组参数。 通过实现ApplicationRunner或CommandLineRunner接口,可以实现在Spring Boot应用程序启动后执行某些操作,比如初始化数据、加载配置文件等。 2. @PostConstruct和@PreDestroy @PostConstruct和@PreDestroy是JavaEE规范中定义的注解,可以用于指定在Bean初始化和销毁时执行的方法。在Spring Boot应用程序中,也可以使用这两个注解来定义Bean初始化和销毁时执行的方法。 通过在Bean中添加@PostConstruct注解,可以指定一个方法在Bean初始化时执行。同样地,通过在Bean中添加@PreDestroy注解,可以指定一个方法在Bean销毁时执行。 3. SpringApplicationRunListener SpringApplicationRunListener是Spring Boot中用于监听应用程序启动和停止事件的接口。通过实现该接口,可以在应用程序启动和停止时执行一些操作,比如记录日志、加载配置文件等。 通过实现SpringApplicationRunListener接口,可以自定义应用程序启动和停止时的行为,比如在应用程序启动时加载一些自定义配置文件,或者在应用程序停止时清理一些资源。 总之,Spring Boot提供了很多钩子函数,可以用于扩展和定制应用程序的行为,满足开发者的各种需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yzgu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值