Insight AutoConfigureAfter 实现

springboot启动过程中,自动注册配置的初始化顺序可以通过@AutoConfigureBefore @AutoConfigureAfter 实现。比如Mybatis自动配置需要在DataSource 自动配置之后初始化,AutoConfigureAfter 是如何实现的

@AutoConfigureAfter 使用场景

@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisAutoConfiguration {}

@AutoConfigureBefore(WebMvcAutoConfiguration.class)
public class ErrorMvcAutoConfiguration {}

AutoConfigureAfter 原理

解释:

  1. AutoConfigureAfter 声明 当前配置应该在 指定配置之后初始化
  2. AutoConfigureBefore 声明 当前配置应该在 指定配置之前初始化
  3. 一种宽泛的顺序指定,代码中会有算法实现,AutoConfigureBefore 逻辑稍微有些绕

实现关键类:org.springframework.boot.autoconfigure.AutoConfigurationSorter
上下文:@EnableAutoConfiguration 的实现过程中,会选择适合的auto-configuration 配置项,如上述的 DataSourceAutoConfiguration 和 MybatisAutoConfiguration ,筛选完毕后会进行排序,排序首先根据order,然后会根据指定的@AutoConfigureBefore @AutoConfigureAfter 再次调整先后顺序,最后根据此顺序进行初始化。

AutoConfigureAfter 实现

排序过程源码如下:

// AutoConfigurationSorter#getInPriorityOrder
public List<String> getInPriorityOrder(Collection<String> classNames) {
	List<String> orderedClassNames = new ArrayList<String>(classNames);
	// Initially sort alphabetically
	Collections.sort(orderedClassNames);
	// Then sort by order
	Collections.sort(orderedClassNames, new Comparator<String>() {
		//...
	});
	// Then respect @AutoConfigureBefore @AutoConfigureAfter
	// sortByAnnotation 方法是的排序的实现。一个LinkedHashSet 存储和调整顺序,一个LinkedHashSet 用于循环依赖检测
	// 排序算法:循环toSort,从toSort 逐个取出当前元素。递归检测当前元素前后依赖,如果遇到依赖元素(源码-变量after),则先添加依赖after至sorted,再把当前元素添加至sorted
	orderedClassNames = sortByAnnotation(classes, orderedClassNames);
	return orderedClassNames;
}

特别的,需要明确AutoConfigureAfter 、AutoConfigureBefore 的直接作用:

  1. 内部类AutoConfigurationClasse 封装以上两个注解的作用,分别体现在属性before、 after
  2. 内部类AutoConfigurationClasses 封装依赖的检测和计算
  3. 关键的计算方法 AutoConfigurationClasses#getClassesRequestedAfter,如下
// 获取当前class 的所有依赖配置class(强依赖,弱依赖)
public Set<String> getClassesRequestedAfter(String className) {
	Set<String> rtn = new LinkedHashSet<String>();
	// 获取所有的前置class
	rtn.addAll(get(className).getAfter());
	for (Map.Entry<String, AutoConfigurationClass> entry : this.classes
			.entrySet()) {
		// 获取别的class 的后置class,也就是,当前class 的前置class
		if (entry.getValue().getBefore().contains(className)) {
			rtn.add(entry.getKey());
		}
	}
	return rtn;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值