1.概述
有些时候,我们需要在spring启动过程中加入一些自己的逻辑,特别是一些基本框架和spring做整合的时候(例如:mybatis-spring-boot-starter),就需要使用Spring给我们预留的扩展接口。本文将介绍3个常用的初始化扩展接口:
2.spring初始化
下图是spring启动中,初始化ApplicationContext的3个基本步骤
Spring在初始化每个阶段都提供了一些“Hook”,提供给开发者进行扩展(开闭原则)
3.Hook
3.1 BeanFactoryPostProcessor
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
在ApplicationContext中BeanFactory所有的Bean 的定义已经加载完成,但还未实例化,这个时候可以使用该接口对Bean的属性进行覆盖和设置。
简单的例子:修改Bean的属性
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition myService = beanFactory.getBeanDefinition("myService");
myService.getPropertyValues().add("name", "Lizo");
}
}
使用方法:
在BeanFactory中新增(或修改既有的)BeanDefinition,例如
mockito创建mockBean
3.2 BeanPostProcessor
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
该接口的作用是在Bean创建对象以后,在bean初始化前后提供回调方法,做一些定制化处理(例如包装成代理对象,bean对象注解处理)。
spring中大量存在BeanPostProcessor的实现类,来完成特定逻辑,下面只是一个简单的例子
简单例子:对@Service注解的Bean,打印当前BeanName
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
} @Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
Service annotation = AnnotationUtils.findAnnotation(bean.getClass(), Service.class);
if (annotation != null) {
System.out.println(beanName);
}
return bean;
}
}
使用方法:
1.Dubbo中远程调用代理类
2.@PostConstruct注解处理
和InitializingBean,@PostConstruct,XxxAware的执行顺序
XxxAware 类似ApplicationContextAware
3.3 ApplicationListener
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
}
如果是BeanPostProcessor是在Bean初始化前后提供回调,那ApplicationListener就是在ApplicationContext的启动不同阶段提供回调。
根据监听的事件ApplicationEvent来完成回调。常用的事件:
其中可能用的最多的就是ContextRefreshedEvent这个时间。例如有些逻辑要放在整个ApplicationContext完全初始完成之后再执行。
简单例子:ApplicationContext初始完后,把所有BeanPostProcessor实现类设置为null
@Component
public class MyApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContext applicationContext = event.getApplicationContext();
Map<String, BeanPostProcessor> beansOfType = applicationContext.getBeansOfType(BeanPostProcessor.class);
beansOfType.forEach((k,v)->{
v = null;
});
}
}
4.小结
以上3个是Spring中对Bean进行扩展的常用接口,可以通过这些接口新增,修改,代理,校验等逻辑在spring初始化过程中运行。