spring boot 自动装配 bean 的顺序
来源:9-2 不再随意设置数据类型,不给未来留隐患
笑看从前小菜哥
2020-11-03
首先在一哥结婚的这个日子里我来提问,说明一下,我就是故意来提问的。这都是韭菜教我来提问的。
现在这里恭喜一哥 新婚快乐,早生贵子。然后后面是我的提问。
前几天我这边在自定义 bean 的时候遇到了一个比较严重的问题,我的 baen 要求要在其中一个bean之后实例化,但是一直不能实现哪个功能,我加了 @ConditionalOnBean
这个注解之后,他直接就不生效了,就是直接不会创建这个bean,然后我有使用了 @AutoConfigureAfter
,想着在哪个bean之后在实例化,照耀没有生效,最后百度后,查到@AutoConfigureAfter
是要在 spring.factories
中声明后才有效,那一哥能不能给我讲解下这块的原理和 bean加载顺序吗。
2回答
-
张勤一
2020-11-09
小菜哥你好:
其实你这里所说的,我估计应该是你自定义的 Bean 存在着依赖关系,那么,你最好(因为足够简单)使用的应该是 @DependsOn 注解。同时,这个注解是 Spring 框架提供的,更加具有通用性,而你所说的 @AutoConfigureAfter 则是 SpringBoot 提供的。
@AutoConfigureAfter、@AutoConfigureBefore、@AutoConfigureOrder 其实现原理基本都是在 getInPriorityOrder() 方法中通过 ASCII、Sort值、before/after 来排序的,你可以看到源码实现:
public List<String> getInPriorityOrder(Collection<String> classNames) { final AutoConfigurationSorter.AutoConfigurationClasses classes = new AutoConfigurationSorter.AutoConfigurationClasses(this.metadataReaderFactory, this.autoConfigurationMetadata, classNames); List<String> orderedClassNames = new ArrayList(classNames); // 首先根据 ASCII 来进行排序 Collections.sort(orderedClassNames); // 根据 Order Collections.sort(orderedClassNames, new Comparator<String>() { public int compare(String o1, String o2) { int i1 = classes.get(o1).getOrder(); int i2 = classes.get(o2).getOrder(); return i1 < i2 ? -1 : (i1 > i2 ? 1 : 0); } }); // 根据 @AutoConfigureAfter @AutoConfigureBefore List<String> orderedClassNames = this.sortByAnnotation(classes, orderedClassNames); return orderedClassNames; }
而 @DependsOn 就简单了,简言之就是当在构造 “BeanA”的过程中发现其标注有 @DependsOn 的话,就会先调用一遍其中指定的 beans 的构造流程:
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { ... // Guarantee initialization of beans that the current bean depends on. String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { // 循环所有 dependsOn 的 bean名 if (isDependent(beanName, dep)) { // 校验一下是否存在循环所 dependsOn,循环dependsOn是不允许的 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } registerDependentBean(dep, beanName); // 注册dependsOn关系,用于上边校验循环dependsOn用 try { getBean(dep); // 让被依赖的bean先走构造流程 } catch (NoSuchBeanDefinitionException ex) { // 用被依赖的bean名无法构造bean需要抛出异常 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } ... }
我是勤一,致力于将这门课程的问答区打造为 Java 知识体系知识库,Java 知识体系 BBS!共同建造、维护这门课程,我需要每一个你!
10 -
qq_电耗子_0
2020-11-03
删了吧 没救了
112020-11-03
相似问题