BeanPostProcessor 接口是 Spring 提供的众多接口之一,他的作用主要是如果需要在Spring 容器完成 Bean 的实例化、配置和其他的初始化前后添加一些自己的逻辑处理,可以通过实现 BeanPostProcessor 来完成。
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// bean初始化方法调用前被调用
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// bean初始化方法调用后被调用
return bean;
}
}
运行顺序:
----------------Spring IOC容器实例化Bean
----------------调用BeanPostProcessor的postProcessBeforeInitialization方法
----------------调用bean实例的初始化方法
----------------调用BeanPostProcessor的postProcessAfterInitialization方法
BeanFactoryPostProcessor 接口与 BeanPostProcessor 接口类似,可以对bean的定义(配置元数据)进行处理;也就是spring ioc运行BeanFactoryPostProcessor 在容器实例化任何其他的bean之前读取配置元数据,并有可能修改它;
如果业务需要,可以配置多个BeanFactoryPostProcessor 的实现类,通过 ”order” 控制执行次序(要实现 Ordered 接口)。
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public MyBeanFactoryPostProcessor() {
System.out.println("----------------execute MyBeanFactoryPostProcessor constructor");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("----------------execute MyBeanFactoryPostProcessor postProcessBeanFactory");
}
}
打印输出:
----------------execute MyBeanFactoryPostProcessor constructor
----------------execute MyBeanFactoryPostProcessor postProcessBeanFactory
postProcessBeanFactory 方法在构造函数方法之后执行。
InitializingBean 接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet 方法,凡是继承该接口的类,在初始化bean的时候都会执行该方法。
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
DisposableBean 也是一个接口,提供了一个唯一的方法destory(),凡是继承该接口的类,在Bean生命周期结束前都会执行该方法。
public interface DisposableBean {
void destroy() throws Exception;
}
FactoryBean 是一个接口,当在 IOC 容器中的 Bean 实现了 FactoryBean 后,通过 getBean(String BeanName) 获取到的Bean对象并不是 FactoryBean 的实现类对象,而是这个实现类中的 getObject() 方法返回的对象。
public interface FactoryBean<T> {
// 获取类对象
@Nullable
T getObject() throws Exception;
// 获取类类型
@Nullable
Class<?> getObjectType();
// 是否单例
default boolean isSingleton() {
return true;
}
}
BeanDefinitionRegistryPostProcessor 可以完成新的 BeanDefinition 注册,对已有 BeanDefinition 进行修改等操作。
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
/**
* 在Spring的标准初始化完成之后,此时所有的符合 Spring 规则的BeanDefinition已经全部完成加载,但是还没有任何一个 Bean 被初始化,
* Spring允许在下一个post-processing开始处理之前通过此接口添加更多的BeanDefinition
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
写一个类实现 BeanDefinitionRegistryPostProcessor 往容器中手动注册一个BeanDefinition。
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
// 创建一个bean的定义类的对象
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(MyMapperFactoryBean.class);
// 将Bean 的定义注册到Spring环境
beanDefinitionRegistry.registerBeanDefinition("myMapperFactoryBean", rootBeanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {// bean的名字为key, bean的实例为value
}
}
MyMapperFactoryBean :
public class MyMapperFactoryBean implements FactoryBean {
@Override
public Object getObject() throws Exception {
// 创建一个代理对象
return Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{TestBeanDefRegPostProMapper.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("----------execute:" + method.getName());
Class<?> returnType = method.getReturnType();
return "xxxxxxxxxxxx";
}
});
}
@Override
public Class<?> getObjectType() {
return TestBeanDefRegPostProMapper.class;
}
}
TestBeanDefRegPostProMapper 接口:
public interface TestBeanDefRegPostProMapper {
String exexute();
}
测试:
@SpringBootApplication
public class SpringbootApplication implements CommandLineRunner {
@Autowired
private TestBeanDefRegPostProMapper testBeanDefRegPostProMapper;
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
System.out.println(testBeanDefRegPostProMapper.exexute());
}
}
测试结果:
----------execute:exexute
xxxxxxxxxxxx
最经典的案例就是Mybatis与Spring集成中的 MapperScannerConfigurer 和 MapperFactoryBean
MapperScannerConfigurer :
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
if (this.processPropertyPlaceHolders) {
processPropertyPlaceHolders();
}
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
scanner.setAddToConfig(this.addToConfig);
scanner.setAnnotationClass(this.annotationClass);
scanner.setMarkerInterface(this.markerInterface);
scanner.setSqlSessionFactory(this.sqlSessionFactory);
scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
scanner.setResourceLoader(this.applicationContext);
scanner.setBeanNameGenerator(this.nameGenerator);
scanner.registerFilters();
// 扫描Mybatis配置MapperScan包,进行注册,将每一个Mapper接口都注册为一个MapperFactoryBean对象
scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
}
}
MapperFactoryBean:
public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {
@Override
public T getObject() throws Exception {
// 返回一个代理对象,用于执行sql
return getSqlSession().getMapper(this.mapperInterface);
}
}
1、实现 BeanNameAware 接口的 Bean,在 Bean 加载的过程中可以获取到该 Bean 的 id。
public interface BeanNameAware extends Aware {
void setBeanName(String beanName);
}
2、实现 ApplicationContextAware 接口的 Bean,在 Bean 加载的过程中可以获取到 Spring的ApplicationContext,ApplicationContext 是 Spring 应用上下文,从 ApplicationContext 中可以获取包括任意的 Bean 在内的大量 Spring 容器内容和信息。
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
3、实现 BeanFactoryAware 接口的 Bean,在 Bean 加载的过程中可以获取到加载该 Bean的BeanFactory。
public interface BeanFactoryAware extends Aware {
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
实现了EnvironmentAware接口重写setEnvironment方法后,可通过 Environment 对象获取运行环境中变量。
public interface EnvironmentAware extends Aware {
void setEnvironment(Environment environment);
}
动态的读取文件,通过该接口可以加载自定义配置文件。
@FunctionalInterface
public interface EnvironmentPostProcessor {
void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application);
}
加载自定义配置文件
public class LizqEnvironmentPostProcessor implements EnvironmentPostProcessor {
private final Properties properties = new Properties();
private String propertiesFile = "lizq.properties";
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
Resource resource = new ClassPathResource(propertiesFile);
environment.getPropertySources().addLast(loadProperties(resource));
}
private PropertySource<?> loadProperties(Resource resource) {
if (!resource.exists()) {
throw new RuntimeException("file not exist");
}
try {
//custom.properties
properties.load(resource.getInputStream());
return new PropertiesPropertySource(resource.getFilename(), properties);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
获取Bean的类装载器。
public interface BeanClassLoaderAware extends Aware {
void setBeanClassLoader(ClassLoader classLoader);
}
获取bean工厂。
public interface BeanFactoryAware extends Aware {
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
取到了该Bean在Spring容器中的名字。
public interface BeanNameAware extends Aware {
void setBeanName(String beanName);
}
在Spring IOC容器创建之后、关闭之前执行自定义的操作。
public interface Lifecycle {
void start(); // 容器启动后调用
void stop(); // 容器关闭前调用
boolean isRunning(); // 当前应用是否正在运行
}
用于在 Spring 容器刷新之前初始化 Spring ConfigurableApplicationContext 的回调接口。(剪短说就是在容器刷新之前调用该类的 initialize()
方法。并将 ConfigurableApplicationContext 类的实例传递给该方法)
通常用于需要对应用程序上下文进行编程初始化的web应用程序中。例如,根据上下文环境注册属性源或激活配置文件等。
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
/**
* Initialize the given application context.
* @param applicationContext the application to configure
*/
void initialize(C applicationContext);
}