Insight Spring 注入排序的集合

西门骁
2023-12-01

背景

项目中需要策略模式来解耦业务的场景,通过组合相同接口的Bean来实现。

策略模式可以避开一长串的if-else,规范性、扩展性也好一些。

使用spring 自动注入的好处是:随着业务的增加,只需要添加具体的实现类即可,无需关注策略的调度和实现。引出的问题是:if-else 旧的代码有default 的处理,如何确保托底策略的bean 是在集合的最后?

// show code 通过spring 注入 FooHandler 处理器实现
@Autowired
public FooService(List<FooHandler> fooHandlers) {
    // 其实这行代码是多余的,注入完成后,fooHandlers 已经按照Order 排序了!!!
	fooHandlers.sort(OrderComparator.INSTANCE);
	this.fooHandlers = fooHandlers;
}

@Override
public void doBusiness(ReceiveMsg msg) throws Exception {
	for (FooHandler handler : fooHandlers) {
        // 需要确保默认的处理器,最后执行
		if (handler.support(msg)) {
			handler.handle(msg);
			return;
		}
	}
	throw new IllegalArgumentException("没有找到符合的处理器,检查入参或者默认的处理器...");
}

Insight-分析

注入过程涉及的主要方法

  • org.springframework.beans.factory.support.ConstructorResolver#autowireConstructor
  • org.springframework.beans.factory.support.ConstructorResolver#createArgumentArray
  • org.springframework.beans.factory.support.ConstructorResolver#resolveAutowiredArgument
  • org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency
  • org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveMultipleBeans

分析

  • 因为程序是构造器注入,入口自然是ConstructorResolver。这里涉及到各种构造器的解析和尝试匹配的实现,兼容性很高。
  • 依赖注入的入口 doResolveDependency,非常核心。主要是处理集合注入、单个注入。
  • 集合注入支持Array、List、Map,Array和List支持排序,Map 为LinkedHashMap。
  • 使用的排序器为:AnnotationAwareOrderComparator,支持@Order 、Ordered接口 和@Priority

总结

spring 注入的集合是排序过的,放心使用。声明排序可以通过@Order 、@Priority 注解,或者实现Ordered接口。

延伸阅读:TimSort

参考:Spring IOC(六)依赖查找

 类似资料: