Spring拓展接口之BeanPostProcessor,咱們來看看它的底層實現

前言

  開心一刻git

    小明:「媽,我被公司開除了」,媽:「啊,爲何呀?」, 小明:「我罵董事長是笨蛋,公司召開高層會議還要起訴我」,媽:「告你誹謗是吧?」,小明:「不是,他們說要告我泄露公司機密」spring

BeanPostProcessor定義

  無論三七二十一,咱們先來看看它的定義,看看spring是如何描述BeanPostProcessor的express

/*
 * Copyright 2002-2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory.config;

import org.springframework.beans.BeansException;
import org.springframework.lang.Nullable;

/**
 * 容許對新的bean示例進行自定義的修改,例如檢查標誌接口或進行代理封裝
 *
 * spring上下文會在它的beng定義中自動檢測BeanPostProcessor實例,並將它們應用於隨後建立的每個bean實例
 *
 * implement {@link #postProcessAfterInitialization}.
 * 一般,經過實現BeanPostProcessor的postProcessBeforeInitialization方法(配合標記接口,如@Autowired)來填充bean實例,
 * 經過BeanPostProcessor的postProcessAfterInitialization方法進行bean實例的代理
 *
 */
public interface BeanPostProcessor {

    /**
     * 在bean實例的初始化方法(例如InitializingBean的afterPropertiesSet或自定義的init-method)回調以前,
     * spring會應用此方法到bean實例上。通常用於bean實例的屬性值的填充
     * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
     * initialization callbacks (like InitializingBean's {@code 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.
     * <p>The default implementation returns the given {@code bean} as-is.
     * @param bean the new bean instance
     * @param beanName the name of the bean
     * @return the bean instance to use, either the original or a wrapped one;
     * if {@code null}, no subsequent BeanPostProcessors will be invoked
     * @throws org.springframework.beans.BeansException in case of errors
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
     */
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    /**
     * 在bean實例的初始化方法(例如InitializingBean的afterPropertiesSet或自定義的init-method)回調以後,
     * spring會應用此方法到bean實例上。
     * 在有FactoryBean時,此方法會在FactoryBean實例與FactoryBean的目標對象建立時各調用一次
     * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
     * initialization callbacks (like InitializingBean's {@code 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.
     * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
     * instance and the objects created by the FactoryBean (as of Spring 2.0). The
     * post-processor can decide whether to apply to either the FactoryBean or created
     * objects or both through corresponding {@code bean instanceof FactoryBean} checks.
     * <p>This callback will also be invoked after a short-circuiting triggered by a
     * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
     * in contrast to all other BeanPostProcessor callbacks.
     * <p>The default implementation returns the given {@code bean} as-is.
     * @param bean the new bean instance
     * @param beanName the name of the bean
     * @return the bean instance to use, either the original or a wrapped one;
     * if {@code null}, no subsequent BeanPostProcessors will be invoked
     * @throws org.springframework.beans.BeansException in case of errors
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
     * @see org.springframework.beans.factory.FactoryBean
     */
    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

}
View Code

  簡單點來理解,就是spring會自動從它的全部的bean定義中檢測BeanPostProcessor類型的bean定義,而後實例化它們,再將它們應用於隨後建立的每個bean實例,在bean實例的初始化方法回調以前調用BeanPostProcessor的postProcessBeforeInitialization的方法(進行bean實例屬性的填充),在bean實例的初始化方法回調以後調用BeanPostProcessor的postProcessAfterInitialization的方法(能夠進行bean實例的代理封裝)apache

應用示例

  咱們先來看個簡單的示例,注意:因爲spring只是從spring容器中的bean定義中自動檢測BeanPostProcessor類型的bean定義,因此咱們自定義的BeanPostProcessor要經過某種方式註冊到spring容器app

  MyBeanPostProcessorless

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    public MyBeanPostProcessor () {
        System.out.println("MyBeanPostProcessor 實例化......");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("spring中bean實例:" + beanName + " 初始化以前處理......");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("spring中bean實例:" + beanName + " 初始化以後處理......");
        return bean;
    }
}
View Code

  AnimalConfigide

@Configuration
public class AnimalConfig {

    public AnimalConfig() {
        System.out.println("AnimalConfig 實例化");
    }

    @Bean
    public Dog dog() {
        return new Dog();
    }

}
View Code

  Dogspring-boot

public class Dog {

    private String name;

    public Dog() {
        System.out.println("Dog 實例化......");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
View Code

  完整實例工程:spring-boot-BeanPostProcessor 咱們來看看啓動結果post

  有人可能會說了:「你是個逗比把,你舉的這個例子有什麼用? 實際上,根本就不會出現BeanPostProcessor的這樣用法!」  有這樣的疑問很是正常,示例中的BeanPostProcessor的兩個方法:postProcessBeforeInitialization、postProcessAfterInitialization沒作任何的處理,都只是直接返回bean,這不就是:脫了褲子放屁?ui

  咱們細看下,會發現postProcessBeforeInitialization、postProcessAfterInitialization中各多了一行打印(),其實示例只是驗證下Spring對BeanPostProcessor的支持、BeanPostProcessor的兩個方法的執行時機,是否如BeanPostProcessor 的註釋所說的那樣,實際應用中確定不會這麼用的。那問題來了:BeanPostProcessor能用來幹什麼? 回答這個問題以前,咱們先來看看spring對BeanPostProcessor的底層支持

源碼解析

  BeanPostProcessor的實例化與註冊  

    很明顯,咱們從spring的啓動過程的refresh方法開始,以下圖

 

    此時spring容器中全部的BeanPostProcessor都進行了實例化,並註冊到了beanFactory的beanPostProcessors屬性中

    registerBeanPostProcessors

public static void registerBeanPostProcessors(
        ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

    // Register BeanPostProcessorChecker that logs an info message when
    // a bean is created during BeanPostProcessor instantiation, i.e. when
    // a bean is not eligible for getting processed by all BeanPostProcessors.
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

    // Separate between BeanPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    // 將全部BeanPostProcessor bean定義分三類:實現了PriorityOrdered、實現了Ordered,以及剩下的常規BeanPostProcessor
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            // 實例化實現了PriorityOrdered接口的BeanPostProcessor
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            priorityOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // First, register the BeanPostProcessors that implement PriorityOrdered.
    // 註冊實現了PriorityOrdered接口的BeanPostProcessor到beanFactory的beanPostProcessors屬性中
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

    // Next, register the BeanPostProcessors that implement Ordered.
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
    for (String ppName : orderedPostProcessorNames) {
        // 實例化實現了Ordered接口的BeanPostProcessor
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        orderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    // 註冊實現了Ordered接口的BeanPostProcessor到beanFactory的beanPostProcessors屬性中
    sortPostProcessors(orderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);

    // Now, register all regular BeanPostProcessors.
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
    for (String ppName : nonOrderedPostProcessorNames) {
        // 實例化剩下的全部的常規的BeanPostProcessors
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        nonOrderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

    // Finally, re-register all internal BeanPostProcessors.
    // 註冊全部常規的的BeanPostProcessor到beanFactory的beanPostProcessors屬性中
    sortPostProcessors(internalPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, internalPostProcessors);

    // Re-register post-processor for detecting inner beans as ApplicationListeners,
    // moving it to the end of the processor chain (for picking up proxies etc).
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
View Code

  BeanPostProcessor的生效時機

    前面咱們已經知道,spring會應用BeanPostProcessor於隨後建立的每個bean實例,具體spring是如何作到的了,咱們仔細來看看

    finishBeanFactoryInitialization方法實例化全部剩餘的、非延遲初始化的單例(默認狀況下spring的bean都是非延遲初始化單例),具體以下

BeanPostProcessor應用場景

  其實只要咱們弄清楚了BeanPostProcessor的執行時機:在bean實例化以後、初始化先後被執行,容許咱們對bean實例進行自定義的修改;只要咱們明白了這個時機點,咱們就能分辨出BeanPostProcessor適用於哪些需求場景,哪些需求場景能夠用BeanPostProcessor來實現

  spring中有不少BeanPostProcessor的實現,咱們接觸的比較多的自動裝配:AutowiredAnnotationBeanPostProcessor也是BeanPostProcessor的實現之一,關於自動裝配我會在下篇博文中與你們一塊兒探索

總結

  spring中bean的生命週期以下圖

    引用自:Spring實戰系列(三)-BeanPostProcessor的妙用

相關文章
相關標籤/搜索