天天看點

Spring後置處理器BeanPostProcessor源碼解析

引言

如果對

BeanPostProcessor

的使用不是很了解的,可以參考另一篇文章:

https://blog.csdn.net/zxd1435513775/article/details/83019572

BeanPostProcessor

也稱為Bean後置處理器,它是Spring中定義的接口,在Spring容器的建立過程中會回調

BeanPostProcessor

中定義的兩個方法。

BeanPostProcessor

源碼如下:

public interface BeanPostProcessor {

	Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

	Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}
           
具體在什麼時候調用這兩個方法呢?

postProcessBeforeInitialization

方法會在每一個bean對象的初始化方法調用之前回調

postProcessAfterInitialization

方法會在每個bean對象的初始化方法調用之後被回調

自定義BeanPostProcessor

由上面

BeanPostProcessor

源碼可以看到它兩個方法的參數都相同,其中:

  • 第一個參數Object bean表示目前正在初始化的bean對象。
  • 兩個方法都傳回Object類型的執行個體,傳回值既可以是将入參Object bean原封不動的傳回出去,也可以對目前bean進行包裝再傳回

來看看下面的自定義

BeanPostProcessor

// 後置處理器:在每一個bean初始化前後進行處理工作,需要将後置處理器加入到容器中
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization..."+beanName+"..."+bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization..."+beanName+"..."+bean);
        return bean;
    }
}
           
Spring容器中加入MyBeanPostProcessor之後,針對容器中每個建立的Bean對象,既包括Spring自身建立的Bean,也包括應用程式建立的Bean,都會回調

postProcessBeforeInitialization

postProcessAfterInitialization

方法。

執行原理

BeanPostProcessor

的執行是在容器的重新整理過程中,容器重新整理對象具體的方法為:

在refresh方法執行的調用棧中會去調用

AbstractAutowireCapableBeanFactory.doCreateBean()

方法,該方法節選源碼如下

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged(new PrivilegedAction<Object>() {
			@Override
			public Object run() {
				invokeAwareMethods(beanName, bean);
				return null;
			}
		}, getAccessControlContext());
	}else {
		invokeAwareMethods(beanName, bean);
	}

	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
        // 調用postProcessBeforeInitialization方法
		wrappedBean = applybeanpostprocessorsbeforeinitialization(wrappedbean, beanname);
	}

	try {
        // 調用初始化方法
		invokeInitMethods(beanName, wrappedBean, mbd);
	}catch (Throwable ex) {
		throw new BeanCreationException(
				(mbd != null ? mbd.getResourceDescription() : null),
				beanName, "Invocation of init method failed", ex);
	}

	if (mbd == null || !mbd.isSynthetic()) {
        // 調用postProcessAfterInitialization方法
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}
	return wrappedBean;
}
           

看到在調用初始化方法前後會分别調用

applyBeanPostProcessorsBeforeInitialization()

applyBeanPostProcessorsAfterInitialization()

applyBeanPostProcessorsBeforeInitialization()

方法的源碼如下:

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {

	Object result = existingBean;
	// 會拿到所有的BeanPostProcessor,進行逐一周遊
	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
		result = beanProcessor.postProcessBeforeInitialization(result, beanName);
		if (result == null) {
			return result;
		}
	}
	return result;
}


public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {

	Object result = existingBean;
    // 會拿到所有的BeanPostProcessor,進行逐一周遊
	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
		result = beanProcessor.postProcessAfterInitialization(result, beanName);
		if (result == null) {
			return result;
		}
	}
	return result;
}
           

可以看到其邏輯為:

周遊得到容器中所有的

BeanPostProcessor

,然後執行

postProcessBeforeInitialization

,一但傳回null,就跳出for循環,不執行後面的

BeanPostProcessor.postProcessorsBeforeInitialization()

也就是說,如果傳回的是null,那麼我們通過getBean方法将得不到目标Bean。

applyBeanPostProcessorsAfterInitialization()

方法的邏輯和上面一緻,Spring底層的很多功能特性都是借助

BeanPostProcessor

的子類來實作。

BeanPostProcessor

的繼承結構如下:

Spring後置處理器BeanPostProcessor源碼解析

常見BeanPostProcessor分析

下圖是debug過程中,

ApplicationContext

對象中的包含的

BeanPostProcessor

。具體包含哪些

BeanPostProcessor

與具體應用程式相關,除了下标3中的

MyBeanPostProcessor

為自定義的

BeanPostProcessor

,其餘均為Spring自帶的

BeanPostProcessor

Spring後置處理器BeanPostProcessor源碼解析

下面來分析一下

ApplicationContextAwareProcessor

AutowiredAnnotationProcessor

的執行原理。

ApplicationContextAwareProcessor

ApplicationContextAwareProcessor

後置處理器的作用是:當應用程式定義的Bean實作ApplicationContextAware接口時注入ApplicationContext對象

@Component
public class Car implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    public Car(){
        System.out.println("car instance...");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("ApplicationContextAware...setApplicationContext()");
        this.applicationContext = applicationContext;
    }
}
           

那Car是如何通過實作

ApplicationContextAware

接口就能獲得

ApplicationContext

對象呢?

答案:通過

ApplicationContextAwareProcessor

後置處理器來實作,下面來看看

ApplicationContextAwareProcessor

的源碼

// 實作BeanPostProcessor接口
class ApplicationContextAwareProcessor implements BeanPostProcessor {

    private final ConfigurableApplicationContext applicationContext;

    private final StringValueResolver embeddedValueResolver;

    /**
     * Create a new ApplicationContextAwareProcessor for the given context.
     */
    public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
        this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
    }

    // 實作BeanPostProcessor接口中的postProcessBeforeInitialization
    @Override
    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        
        AccessControlContext acc = null;
        // 這裡bean是Car,它實作了ApplicationContextAware接口
        if (System.getSecurityManager() != null &&
                (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                        bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                        bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
            
            // 如果實作了ApplicationContextAware接口,就是執行下面方法
            invokeAwareInterfaces(bean);
        }

        return bean;
    }

    // 這裡bean是Car
    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof EnvironmentAware) {
                ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
            }
            if (bean instanceof EmbeddedValueResolverAware) {
                ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
            }
            if (bean instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
            }
            if (bean instanceof ApplicationEventPublisherAware) {
                ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
            }
            if (bean instanceof MessageSourceAware) {
                ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
            }
            // 此條件成立
            if (bean instanceof ApplicationContextAware) {
                // 會執行這裡回調car重寫的setApplicationContext方法,然後将this.applicationContext注入給Car
                ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
            }
        }
    }

    // 實作BeanPostProcessor接口中的postProcessAfterInitialization
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }
}
           

InitDestroyAnnotationBeanPostProcessor

InitDestroyAnnotationBeanPostProcessor

後置處理器是用來處理自定義的初始化方法和銷毀方法。

Spring中提供了3種自定義初始化和銷毀方法:

  • 通過

    @Bean

    注解指定

    init-method

    destroy-method

    屬性
  • Bean實作

    InitializingBean

    (定義初始化邏輯),

    DisposableBean

    (定義銷毀邏輯)兩個接口
  • @PostConstruct:在bean建立完成并且屬性指派完成,來執行初始化方法@PreDestroy,在容器銷毀bean之前通知我們進行清理工作

InitDestroyAnnotationBeanPostProcessor

的作用就是讓第3種方式生效。

先看看如何使用

@PostConstruct

@PreDestroy

注解。

@Component
public class Car {

    public Car(){
        System.out.println("car instance...");
    }

    // 自定義的初始化方法
    @PostConstruct
    public void init(){
        System.out.println("car ... init...");
    }

    // 自定義的銷毀方法
    @PreDestroy
    public void detory(){
        System.out.println("car ... detory...");
    }
}
           

InitDestroyAnnotationBeanPostProcessor

會在Bean建立的時候通過反射的方式查找包含

@PostConstruct

@PreDestroy

注解的方法,然後再通過反射執行方法。

我們來看看

InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization()

的源碼

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    
    // 擷取bean的metadata
    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
   
    try {
        // 執行@PostConstruct指定的init方法
        metadata.invokeInitMethods(bean, beanName);
        
    } catch (InvocationTargetException ex) {
        throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
    } catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
    }
    return bean;
}
           

metadata

中已經解析出

initMethods

destroyMethods

,其具體内容如下

Spring後置處理器BeanPostProcessor源碼解析

這個方法調用就是根據反射執行init方法

InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor

也是個接口,它是

BeanPostProcessor

的子接口

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

    //執行個體化Bean之前調用
    Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;

    //執行個體化Bean之後調用
    boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;

    //設定Bean對象中的某個屬性時調用
    PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;

}
           
這兩個接口的功能基本類似,不過要注意

InstantiationAwareBeanPostProcessor

BeanPostProcessor

的方法名差別

InstantiationAwareBeanPostProcessor

中是

Instantiation

BeanPostProcessor

Initialization