自定义BeanFactoryPostProcessor的实现
一:BeanFactoryPostProcessor的执行时机
在自定义BeanFactoryPostProcessor之前,我们需要了解下其执行的时机,才能知道该如何去自定义。
下面,我们看下Spring源码里面BeanFactoryPostProcessor的执行时机。
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
...
this.invokeBeanFactoryPostProcessors(beanFactory);
...
this.finishRefresh();
} catch (BeansException var10) {
this.destroyBeans();
this.cancelRefresh(var10);
} finally {
this.resetCommonCaches();
}
}
}
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
this.refreshBeanFactory();
return this.getBeanFactory();
}
protected final void refreshBeanFactory() throws BeansException {
if (this.hasBeanFactory()) {
this.destroyBeans();
this.closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = this.createBeanFactory();
beanFactory.setSerializationId(this.getId());
this.customizeBeanFactory(beanFactory);
this.loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
} catch (IOException var2) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var2);
}
}
在执行invokeBeanFactoryPostProcessors方法之前,会先执行obtainFreshBeanFactory方法,在该方法中,我们会看到调用了loadBeanDefinitions,会从各种配置中去加载bean的定义信息。
所以,我们可以得出结论,当需要在BeanFactory加载Bean定义后,Bean实例化之前,向BeanFactory中注册新的Bean定义时,可以使用BeanFactoryPostProcessor接口来实现
。
二、自定义BeanFactoryPostProcessor
1、定义需要载入容器的bean信息
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface HandlerType {
String[] value() default {};
}
public abstract class AbstractTaskRetry {
/**
* 监听设备心跳状态
*/
abstract public void heartbeat(HeartbeatDTO heartbeatDTO);
}
@Component
@HandlerType("QC")
public class QcTaskRetryHandler extends AbstractTaskRetry {
@Override
public void heartbeat(HeartbeatDTO heartbeatDTO) {
}
}
@Component
@HandlerType("RTG")
public class RtgTaskRetryHandler extends AbstractTaskRetry {
@Override
public void heartbeat(HeartbeatDTO heartbeatDTO) {
}
}
2、定义BeanFactoryPostProcessor的实现类
public class HandlerContext {
private Map<String, Class> handlerMap;
public HandlerContext(Map<String, Class> handlerMap) {
this.handlerMap = handlerMap;
}
public AbstractTaskRetry getInstance(String type) {
Class clazz = handlerMap.get(type);
if (clazz == null) {
throw new IllegalArgumentException("not found handler for type: " + type);
}
return (AbstractTaskRetry) SpringContextUtil.getBean(clazz);
}
}
@Component
public class FacilityHeartbeatBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
private static final String HANDLER_PACKAGE = "com.jz.iecs.handler.biz";
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
Map<String, Class> handlerMap = Maps.newConcurrentMap();
// 扫描到被HandlerType注解标识的类
ClassScaner.scan(HANDLER_PACKAGE, HandlerType.class).forEach(clazz -> {
String[] handlerTypes = clazz.getAnnotation(HandlerType.class).value();
Arrays.stream(handlerTypes).collect(Collectors.toList()).forEach(type->{
// 为什么此处不放对应的实例bean,而是放了对应的Class类???
// 因为此刻只是加载了bean的定义信息,还没有进行bean的实例化与初始化
handlerMap.put(type, clazz);
});
});
// 将map属性放入HandlerContext,然后将HandlerContext纳入spring容器管理
HandlerContext context = new HandlerContext(handlerMap);
beanFactory.registerSingleton(HandlerContext.class.getName(), context);
}
}
三、使用自动装配注解运用自定义的bean实例
因为在开篇的refresh的执行步骤中,有一个invokeBeanFactoryPostProcessors方法,里面会调用具体的postProcessBeanFactory,逐一进行beanFactory的实例注册。
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
//收集所有BeanFactoryPostProcessor实现类的bean名称
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
regularPostProcessors = new ArrayList();
registryProcessors = new ArrayList();
currentRegistryProcessors = new ArrayList();
postProcessorNames = postProcessorNames;
int var20 = postProcessorNames.length;
String ppName;
for(var9 = 0; var9 < var20; ++var9) {
ppName = postProcessorNames[var9];
if (!processedBeans.contains(ppName)) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
regularPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
} else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
registryProcessors.add(ppName);
} else {
currentRegistryProcessors.add(ppName);
}
}
}
// 优先执行实现PriorityOrdered接口的
sortPostProcessors(regularPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors((Collection)regularPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList(registryProcessors.size());
Iterator var21 = registryProcessors.iterator();
while(var21.hasNext()) {
String postProcessorName = (String)var21.next();
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
// 其次执行实现Ordered接口的
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors((Collection)orderedPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList(currentRegistryProcessors.size());
Iterator var24 = currentRegistryProcessors.iterator();
while(var24.hasNext()) {
ppName = (String)var24.next();
nonOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
// 最后执行既没有实现PriorityOrdered,也没有实现Ordered接口的
invokeBeanFactoryPostProcessors((Collection)nonOrderedPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
beanFactory.clearMetadataCache();
}
private static void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
Iterator var2 = postProcessors.iterator();
while(var2.hasNext()) {
BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor)var2.next();
StartupStep var10000 = beanFactory.getApplicationStartup().start("spring.context.bean-factory.post-process");
postProcessor.getClass();
StartupStep postProcessBeanFactory = var10000.tag("postProcessor", postProcessor::toString);
postProcessor.postProcessBeanFactory(beanFactory);
postProcessBeanFactory.end();
}
}
到此,所有的BeanFactoryPostProcessor的postProcessBeanFactory方法都会被调用,包括我们自定义的BeanFactoryPostProcessor,那么HandlerContext这类我们自己定义的bean实例就会被注册到容器中,我们在使用的过程中,就可以通过自动注入的方式来进行使用。
@Autowired
private HandlerContext handlerContext;
@Override
public void facilityHeartbeat(HeartbeatDTO heartbeatDTO) {
if (StringUtils.isEmpty(heartbeatDTO.getMachType())){
return;
}
handlerContext
// 获取具体的实现类
.getInstance(heartbeatDTO.getMachType())
// 调用具体方法
.process(heartbeatDTO);
}
转载自:https://juejin.cn/post/7372469324983189554