【问题标题】:Spring DeferredImportSelector run before any ConfigurationsSpring DeferredImportSelector 在任何配置之前运行
【发布时间】:2018-09-24 04:19:54
【问题描述】:

我正在尝试创建类似 @Enable... 自动配置的东西。我想为自定义库创建这样的注释,该库具有广泛的 spring 配置,但需要提供 2 个 bean,并基于这些 bean 初始化各种上下文。它确实初始化了数组中返回的所有 @configuration 类中的 bean,但我还想根据已注册的 bean 执行一些自定义配置逻辑。现在的javadoc https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/ImportSelector.html

声明

ImportSelector 通常以与常规 @Import 注释相同的方式处理,但是,也可以延迟选择导入,直到处理完所有 @Configuration 类(有关详细信息,请参阅 DeferredImportSelector)。

所以我转向 DeferredImportSelector,因为据说 Selector 在所有 @Configuration bean 之后运行,所以我可以做条件 Bean。现在javadoc在这里很清楚(https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/DeferredImportSelector.html

ImportSelector 的一种变体,在处理完所有 @Configuration bean 后运行。当所选导入为@conditional

时,这种类型的选择器可能特别有用

所以这对我来说是完美的。好吧,直到事实证明无论我做什么,导入选择器 selectImports 方法总是在所有 @Configuration bean 之前运行。

我发现主 @Configuration bean 可能总是最后一个,而 javadoc 实际上提到了所有导入的 @Configuration bean。看来情况也并非如此。我一直在使用调试器检查优先级,但这是我所做的测试代码,非常简单:

除了 system out 什么都不做的导入选择器:

public class TestImportSelector implements DeferredImportSelector{

 @Override
 public String[] selectImports(AnnotationMetadata arg0) {
     System.out.println("ImportSelector");
     return new String[0];
 }
}

配置类(导入以检查任何提到的想法是否有效)

@Configuration
public class ImportedTestContext {
    @Bean
    public String testBeanString2(){
        System.out.println("bean2");
        return "string2";
    }
}

主上下文类(也尝试交换导入的类)

@Configuration
@Import({TestImportSelector.class, ImportedTestContext.class})
public class TestMainContext {
    @Bean
    public String testBeanString(){
        System.out.println("bean1");
        return "string";
    }
}

最后是我的主要课程

public class Test {    
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(TestMainContext.class);
    }    
}

Sooo,当你运行主程序时。你总是得到相同的输出

ImportSelector
bean2
bean1

无论如何,导入选择器总是第一个。此外,我试图按照 javadoc 所说的那样处理 Ordered 接口

实现还可以扩展 Ordered 接口或使用 Order 注解来指示相对于其他 DeferredImportSelectors 的优先级

但似乎甚至没有调用 getOrder 方法。嗯,这可能是因为它说它只检查其他 DeferredImportSelectors(没有但值得尝试)

我已经使用 spring-context 4.3.2.RELEASE 完成了这项工作,因为这是我的项目中使用的,但只是为了确保也使用 5.0.5.RELEASE 进行了测试。 结果完全一样。

所以我相信我对 ImportSelector、DeferredImportSelector、spring 不了解,或者 javadoc 没有说实话或者我误解了它的可能性很小......

如果有任何帮助或建议,我将不胜感激......

明确一点:基于 DeferredImportSelector,我希望它实现 BeanFactoryAware(这部分有效,Spring 确实注入了 BeanFactory),它将检查已经定义了哪些 bean(比如那些有趣的测试字符串 bean)并基于这将告诉 spring 应该加载哪些额外的配置。基于 javadoc,这就是它的用途.....

【问题讨论】:

    标签: java spring ioc-container spring-bean


    【解决方案1】:

    看起来DeferredImportSelector 的文档有点不清楚。运行了一些测试并检查了代码,原来deferredImport,而不是ImportSelector

    所以,如果你使用DeferredImportSelector,你可以选择一个配置类,导入为deferred

    selectImports 方法将正常执行 - 在配置文件解析/解析期间,因此 - 使用 BeanFactory 检查是否已经加载了其他 bean 的定义肯定是一个坏主意(因为有些可能还没有) .

    最好的方法是将此逻辑放入@Conditional 注释系列(在目标配置类中),并确保在所有用户定义的配置之后对其进行处理。

    【讨论】:

      猜你喜欢
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 2014-04-27
      • 1970-01-01
      • 1970-01-01
      • 2015-07-25
      • 2022-07-01
      • 1970-01-01
      相关资源
      最近更新 更多