springboot之ImportSelector解析

作者: braveheart075 | 来源:发表于2019-05-29 16:47 被阅读5次

DeferredImportSelector

介绍

/**
 * A variation of {@link ImportSelector} that runs after all {@code @Configuration} beans
 * have been processed. This type of selector can be particularly useful when the selected
 * imports are {@code @Conditional}.
 *
 * <p>Implementations can also extend the {@link org.springframework.core.Ordered}
 * interface or use the {@link org.springframework.core.annotation.Order} annotation to
 * indicate a precedence against other {@link DeferredImportSelector}s.
 *
 * <p>Implementations may also provide an {@link #getImportGroup() import group} which
 * can provide additional sorting and filtering logic across different selectors.
 *
 * @author Phillip Webb
 * @author Stephane Nicoll
 * @since 4.0
 */
  • 他是ImportSelector的一个扩展实现。基本是在所有的Configuration中所有bean实例化完成后,才会触发。在Import的类是Conditional的时候,这个类型的Selector特别有用。
  • 主要实现方法是selectImports,返回对应的全类名。

使用

  • 定义三个Configuration。
@Slf4j
public class MyConfiguration1 {
    public MyConfiguration1() {
      log.info("MyConfiguration1 construct...");
    }

    public void execute() {
        log.info("MyConfiguration1 execute...");
    }
}

@Slf4j
public class MyConfiguration2 {
    public MyConfiguration2() {
        log.info("MyConfiguration2 construct...");
    }

    public void execute() {
        log.info("MyConfiguration2 execute...");
    }
}

@Slf4j
public class MyConfiguration3 {
    public MyConfiguration3() {
        log.info("MyConfiguration3 construct...");
    }

    public void execute() {
        log.info("MyConfiguration3 execute...");
    }
}
  • 定一个导入类
public class MyImportSelector implements DeferredImportSelector {
    @Override public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{MyConfiguration1.class.getName(), MyConfiguration2.class.getName(),
            MyConfiguration3.class.getName()};
    }
}
  • 定一个Configuration进行Import
@Slf4j
@Configuration
@Import(MyImportSelector.class)
public class MyConfiguration {
    @Bean
    public Object test() {
        log.info("MyConfiguration create a object bean...");
        return new Object();
    }
}
  • 启动类
@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class,args);
    }
}

可以看到,在Configuration类中的bean实例化后,才执行Import。

ImportSelector

介绍

/**
     * Select and return the names of which class(es) should be imported based on
     * the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
     */

基本就是返回需要被Import到容器中的class。

使用

public class MyImportSelector implements ImportSelector {
    @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{MyConfiguration1.class.getName(), MyConfiguration2.class.getName(),
            MyConfiguration3.class.getName()};
    }
}
  • 看下启动日志


    imps1.png

和Deferred的区别就是他是先Import的。

AnnotationMetadata这个类

这个比较实用。记得之前写过一个分布式任务调度的框架,如果结合springboot,那么在做一些自定义配置的时候就好很多。如:

  • 定义一个注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(MyHttpDeferredImportSelector.class)
public @interface MyHttp {
    String name() default "";
    String value() default "";

}
  • 注解实现类
@Slf4j
public class MyHttpDeferredImportSelector implements DeferredImportSelector {
    @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        importingClassMetadata.getAllAnnotationAttributes(MyHttp.class.getName(),true)
            .forEach((k,v) -> {
                log.info(importingClassMetadata.getClassName());
                log.info("k:{},v:{}",k,String.valueOf(v));
            });
        return new String[0];
    }
}
  • 使用注解
@Slf4j
@MyHttp(name = "myc1",value = "myc1-value")
public class MyConfiguration1 {
    public MyConfiguration1() {
      log.info("MyConfiguration1 construct...");
    }

    public void execute() {
        log.info("MyConfiguration1 execute...");
    }
}

我们运行的时候能看到如下结果:


ann.png

我们能取到使用注解类的所有信息。这样子,在自定义一些处理规则的时候,会方便很多。

总结

ImportSelector这个springboot的钩子,一般配合Import注解使用,功能还是比较强大的。在自定义一些注解的时候,比较好用。

相关文章

网友评论

    本文标题:springboot之ImportSelector解析

    本文链接:https://www.haomeiwen.com/subject/uogytctx.html