Spring支持的扩展接口

本文主要介绍Spring中所支持的常用的扩展接口,Spring非常庞大且已成体系,众多的开发者包括Spring框架的开发者不可能随意改动框架原来来实现个性化的需求,所以提供了许多扩展接口,遵循开闭原则

开闭原则定义:一个软件实体。如类/模块/函都应该对扩展开放,对修改关闭。

BeanPostProcessor 族

BeanPostProcessor是Spring实现『开闭原则』的一大体现,Spring 会在启动的不同阶段调用不同的BeanPostProcessor实现类,而这些BeanPostProcessor实现类由开发者自行实现(也有许多Spring内置的BeanPostProcessor)来实现启动中的各类需求。

实现了BeanPostProcessor及其子类接口的Bean将会被BeanFactory在执行refresh中某些特殊阶段进行回调,可以在这些方法内部修改或添加类似BeanDefinition、创建Bean代理等操作。

很多Spring框架内部使用了BeanPostProcessor来实现一些功能,例如@Autowired功能是通过AutowiredAnnotationBeanPostProcessor来实现。

BeanPostProcessor

1
2
3
4
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

postProcessBeforeInitialization

该方法将在Bean实例化完成,并注入完属性后被调用,但优先于init-methodInitializingBean#afterPropertiesSetInitializingBean#afterPropertiesSet

可以在该方法中返回包装对象或代理对象。

如果此方法返回null,那么后续的BeanPostProcessor将不会被调用。

postProcessAfterInitialization

该方法在postProcessBeforeInitializationInitializingBean#afterPropertiesSetinit-method调用完成之后被调用。

可以在该方法中返回包装对象或代理对象。

如果此方法返回null,那么后续的BeanPostProcessor将不会被调用。

InstantiationAwareBeanPostProcessor

1
2
3
4
5
6
7
8
9
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;

boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;

PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;

}

postProcessBeforeInstantiation

该方法在实例化Bean之前调用,可以在此处返回代理对象。

如果该方法返回值不为null,那么其余的实例化操作将会被短路short-circuited,包括其余的InstantiationAwareBeanPostProcessor和实例属性的注入(populate),但是会执行所有的BeanPostProcessor#postProcessAfterInitialization

postProcessAfterInstantiation

该方法在实例化Bean之后,注入属性之前被调用。

如果该方法返回true,那么后续的属性注入将被执行;如果返回false,那么将不执行属性的注入,也不会执行其他InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation方法。

该方法适合在自动注入属性前进行自定义字段的注入。

postProcessPropertyValues

该方法在postProcessAfterInstantiation方法调用之后,注入参数之前被调用,可以在此方法中添加或修改需要注入到Bean中的参数。

@Resource@Autowire等注解就是在此处实现自动注入的,扫描对应字段的注解,并将获取到的参数值传入该方法返回值PropertyValues中,后续Spring 将自动把参数注入到对应的字段中。

如果该方法返回null,将不会执行属性的注入,也不会执行其他InstantiationAwareBeanPostProcessor#postProcessPropertyValues方法。

SmartInstantiationAwareBeanPostProcessor

1
2
3
4
5
6
7
8
9
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {

Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException;

Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException;

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

}

predictBeanType

预测并返回Bean的实际类型,如果无法预测可以返回null,一般在BeanDefinition无法确定Bean类型时调用。

determineCandidateConstructors

Bean实例化前被调用,用来确认实例化需要调用的构造方法候选列表。

如果返回不为null,那么不会执行其他的SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors,Spring将会在该返回列表中选择一个方法进行调用。如果所有的SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors均返回null,那么将使用默认的无参构造方法进行调用.

getEarlyBeanReference

出现循环依赖时将会被调用,通过此方法返回一个Bean的引用。

MergedBeanDefinitionPostProcessor

1
2
3
4
5
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {

void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);

}

postProcessMergedBeanDefinition

该方法在合并完Bean定义后被调用。

例如AutowiredAnnotationBeanPostProcessor将在此处解析所有带@Autowire注解的参数。

BeanFactoryPostProcessor 族

BeanFactoryPostProcessor

1
2
3
4
5
public interface BeanFactoryPostProcessor {

void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

postProcessBeanFactory

该方法在所有BeanDefinition被加载完成后,Bean初始化之前被调用。

可以在此处修改已加载的BeanDefinition,或添加自定义的BeanDefinition,来实现动态注册Bean

BeanDefinitionRegistryPostProcessor

1
2
3
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}

postProcessBeanDefinitionRegistry

该方法在所有BeanDefinition被加载完成后,BeanFactoryPostProcessor#postProcessBeanFactory之前被调用。

可以在此处修改已加载的BeanDefinition,或添加自定义的BeanDefinition,来实现动态注册Bean;也可以在此方法中注册其他BeanDefinitionRegistryPostProcessor,但如果当前Bean也是被其他BeanDefinitionRegistryPostProcessor#postProcessBeanFactory加载的,那么当前Bean加载的BeanDefinitionRegistryPostProcessor将没有机会被执行。

Aware 族

实现了Aware接口的Bean将会在特定的场景中被Spring回调,并传入对应的参数供Bean使用。

BeanNameAware

setBeanName

该方法在Bean实例化完成并注入属性后,BeanPostProcessor#postProcessBeforeInitialization方法前被调用。

Bean的名称将会从入参中被传入,该name可能会被添加例如#之类的前缀标识符,如果想要获得原始的name,可以调用BeanFactoryUtils#originalBeanName(String)

BeanClassLoaderAware

setBeanClassLoader

该方法在Bean实例化完成并注入属性后,BeanPostProcessor#postProcessBeforeInitialization方法前被调用。

BeanclassLoader将会被传入。

BeanFactoryAware

setBeanFactory

该方法在Bean实例化完成并注入属性后,BeanPostProcessor#postProcessBeforeInitialization方法前被调用。

持有当前BeanBeanFactory将会被传入。

EnvironmentAware

setEnvironment

该方法将被ApplicationContextAwareProcessor#postProcessBeforeInitialization调用,即在Bean实例化完成,并注入完属性后被调用,但优先于InitializingBean#afterPropertiesSetinit-method

将从入参传入Environment

EmbeddedValueResolverAware

setEmbeddedValueResolver

该方法将被ApplicationContextAwareProcessor#postProcessBeforeInitialization调用,即在Bean实例化完成,并注入完属性后被调用,但优先于InitializingBean#afterPropertiesSetinit-method

将从入参传入StringValueResolver

ResourceLoaderAware

setResourceLoader

该方法将被ApplicationContextAwareProcessor#postProcessBeforeInitialization调用,即在Bean实例化完成,并注入完属性后被调用,但优先于InitializingBean#afterPropertiesSetinit-method

将从入参传入ResourceLoader

ApplicationEventPublisherAware

setApplicationEventPublisher

该方法将被ApplicationContextAwareProcessor#postProcessBeforeInitialization调用,即在Bean实例化完成,并注入完属性后被调用,但优先于InitializingBean#afterPropertiesSetinit-method

将从入参传入ApplicationEventPublisher

MessageSourceAware

setMessageSource

该方法将被ApplicationContextAwareProcessor#postProcessBeforeInitialization调用,即在Bean实例化完成,并注入完属性后被调用,但优先于InitializingBean#afterPropertiesSetinit-method

将从入参传入MessageSource

ApplicationContextAware

setApplicationContext

该方法将被ApplicationContextAwareProcessor#postProcessBeforeInitialization调用,即在Bean实例化完成,并注入完属性后被调用,但优先于InitializingBean#afterPropertiesSetinit-method

将从入参传入ApplicationContext

Other

FactoryBean

1
2
3
4
5
public interface FactoryBean<T> {
T getObject() throws Exception;
Class<?> getObjectType();
boolean isSingleton();
}

FactoryBean是一个定义工厂Bean的接口,如果一个Bean实现了这个接口,那么Spring在初始化的时候会创建该类型的实例,在通过该实例创建其对应的Bean

FactoryBean有三个方法需要子类来实现

isSingleton方法用来返回当前FactoryBean创建的Bean是否为单例,如果返回true表示是单例(singleton)模式的Bean,如果返回false,表示是原型模式(prototype)的Bean

getObjectType方法用来返回该FactoryBean将会创建的Bean的类型。

getObject方法返回创建的Bean,当Spring需要通过FactoryBean创建一个新的Bean的时候,将会调用FactoryBean#getObject来获取Bean并放入IOC容器中。

AbstractFactoryBean

AbstractFactoryBean继承自FactoryBean,提供了getObject方法的默认实现并添加了两个抽象方法需要子类实现。一般情况下,AbstractFactoryBean需要实现四个方法

isSingletonFactoryBean中的isSingleton方法相同。

getObjectTypeFactoryBean中的getObjectType方法相同。

createInstanceFactoryBean中的createInstance方法相同,即AbstractFactoryBean中不需要实现createInstance方法。

destroyInstance方法将在Bean被销毁前调用,用来手动处理Bean销毁前需要处理的工作,例如关闭资源等。

InitializingBean

1
2
3
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}

实现了InitializingBeanBean将在实例化完成后被回调,具体时机是Bean属性注入完成、BeanNameAwareBeanClassLoaderAwareBeanFactoryAware三类Aware回调完成、BeanPostProcessor#postProcessBeforeInitialization调用完成之后,BeanPostProcessor#postProcessAfterInitialization之前。

此时,Bean已经基本初始化完成,此时可以在此方法内部做诸如参数校验、最终初始化等操作。

DisposableBean

1
2
3
public interface DisposableBean {
void destroy() throws Exception;
}

实现了DisposableBeanBean将在销毁前被回调。

可以在该方法内部做最后的清理工作,例如关闭资源等。

ApplicationRunner

1
2
3
public interface ApplicationRunner {
void run(ApplicationArguments args) throws Exception;
}

Spring将在刷新完上下文之后,依次调用所有实现了ApplicationRunner接口Bean的’run’方法。

CommandLineRunner

1
2
3
public interface CommandLineRunner {
void run(String... args) throws Exception;
}

Spring将在刷新完上下文之后,依次调用所有实现了CommandLineRunner接口Beanrun方法,与ApplicationRunner的差别是CommandLineRunner会将启动命令行中的参数传入run方法。

ApplicationListener

1
2
3
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
}

实现ApplicationListenerBean将在对应ApplicationEvent事件发生时被回调,对应的事件为ApplicationListener定义的类型参数,可以通过@EventListener实现类似效果。

可以通过ApplicationEventPublisher#publishEvent发布消息

Lifecycle

1
2
3
4
5
6
7
8
9
public interface Lifecycle {

void start();

void stop();

boolean isRunning();

}

实现了Lifecycle接口的Bean,容器会在生命周期中的不同阶段回调对应的方法,可以在这些方法中执行特定的操作。

start会在容器启动的最后阶段被调用,具体时机是创建完所有的Bean之后,ContextRefreshedEvent消息广播、调用ApplicationRunner#run方法之前。一般情况下,Spring容器不会调用start()方法,所以Lifecycle#start不会被调用,所以需要使用SmartLifecycle

stop会在容器关闭前被调用,具体时机是ContextClosedEvent消息广播之后,DisposableBean#destory方法调用之前。

isRunning用来返回当前Bean是否是运行中,如果返回true,那么不会执行start方法,会执行stop方法;如果返回false,那么会执行start方法,不会执行stop方法。

SmartLifecycle

SmartLifecycleLifecycle基础上实现了Phased类,可以用来控制不同SmartLifecycle的执行顺序,并且在容器进行刷新时也会调用start方法。

ImportBeanDefinitionRegistrar

1
2
3
4
5
6
public interface ImportBeanDefinitionRegistrar {

public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);

}

该接口的作用类似与BeanDefinitionRegistryPostProcessor,可以在此处修改已加载的BeanDefinition,或添加自定义的BeanDefinition,来实现动态注册Bean

不同于其他的组件只需要注入IOC容器即可被自动发现并被调用,BeanDefinitionRegistryPostProcessor子类需要通过@Import注解引入方可使用。

registerBeanDefinitions方法将会被ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry调用,ConfigurationClassPostProcessor是通过实现了BeanDefinitionRegistryPostProcessor接口而获得注册BeanDefinition的能力,所以被调用时机与BeanDefinitionRegistryPostProcessor一致。

各类接口调用时机

  1. BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
  2. BeanDefinitionRegistryPostProcessor#postProcessBeanFactory
    1. ImportBeanDefinitionRegistrar#registerBeanDefinitions
  3. BeanFactoryPostProcessor#postProcessBeanFactory
  4. InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
  5. 创建Bean实例
  6. MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
  7. InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
  8. InstantiationAwareBeanPostProcessor#postProcessPropertyValues
  9. Bean属性注入
  10. BeanNameAware#setBeanName
  11. BeanClassLoaderAware#setBeanClassLoader
  12. BeanFactoryAware#setBeanFactory
  13. BeanPostProcessor#postProcessBeforeInitialization
    1. EnvironmentAware#setEnvironment
    2. EmbeddedValueResolverAware#setEmbeddedValueResolver
    3. ResourceLoaderAware#setResourceLoader
    4. ApplicationEventPublisherAware#setApplicationEventPublisher
    5. MessageSourceAware#setMessageSource
    6. ApplicationContextAware#setApplicationContext
  14. InitializingBean#afterPropertiesSet
  15. 执行init-method
  16. BeanPostProcessor#postProcessAfterInitialization
  17. Lifecycle#start
  18. ApplicationRunner#run
  19. CommandLineRunner#run
  20. 广播ContextRefreshedEvent
如果这篇文章对你有帮助,可以请作者喝杯咖啡~