@import/@importResource的理解

总括:

@Import 

1,引入具有@configure注解的配置类---相当于xml的include 

2,引入实现了importSelector,或importBeanDefintionRegister的子类返回的类实例,这种类的顺序前于配置类的顺序---用于初始化前置条件的类

 一般在@Enable***注解使用,就是在这个功能的所有配置加载之前,先加载importEslector中的前置配置

例子1:

 @Import(feignClientsRegister.class)

 punlic @interface EnableFeignClients

feignClientsRegister 中的registerBeanDefinitions就初始化类

例子2:

 public static class MyImportSelector implements ImportSelector {

        /**

         * AnnotationMetadata表示了使用@Import引入MyImportSelector的类的注解meta信息。

         * 在这个例子中,annotationMetadata可以获取到Config类上的注解详细信息。

         */

        @Override

        public String[] selectImports(AnnotationMetadata annotationMetadata) {

            /*System.out.println("class name --> " + annotationMetadata.getClass().getSimpleName());

            System.out.println("className --> " + annotationMetadata.getClassName());

            Set<String> annotationTypes = annotationMetadata.getAnnotationTypes();

            System.out.println(annotationTypes);*/

//            System.out.println("" + annotationMetadat);

            System.out.println("----MyImportSelector-----");

            return new String[] {"cn.xtt.study.spring.imports.Main.Config_1"};---------将被引入的实例

        }

原文:https://blog.csdn.net/xt8469/article/details/82260091 

@ImportResource

直接引入xml方式的配置文件

@PropertySource   

属性文件 

前言

为什么研究这两个注解,是因为在看Spring Boot源码的时候,对于其中大量的EnableXXX都使用了@Import注解,所以决定研究下这个注解,顺便写了一点关于@ImportRescource注解的东西,希望对大家有帮助。

@Import

简介:功能类似XML配置的,用来导入配置类,可以导入带有@Configuration注解的配置类或实现了ImportSelector/ImportBeanDefinitionRegistrar,或者导入普通的POJO(Spring会将其注册成Spring Bean,导入POJO需要使用Spring 4.2以上)。

下面注解源码,源码有比较详细的英文解释:

/**

 * Indicates one or more {@link Configuration @Configuration} classes to import.

 *

 * <p>Provides functionality equivalent to the {@code <import/>} element in Spring XML.

 * Allows for importing {@code @Configuration} classes, {@link ImportSelector} and

 * {@link ImportBeanDefinitionRegistrar} implementations, as well as regular component

 * classes (as of 4.2; analogous to {@link AnnotationConfigApplicationContext#register}).

 *

 * <p>{@code @Bean} definitions declared in imported {@code @Configuration} classes should be

 * accessed by using {@link org.springframework.beans.factory.annotation.Autowired @Autowired}

 * injection. Either the bean itself can be autowired, or the configuration class instance

 * declaring the bean can be autowired. The latter approach allows for explicit, IDE-friendly

 * navigation between {@code @Configuration} class methods.

 *

 * <p>May be declared at the class level or as a meta-annotation.

 *

 * <p>If XML or other non-{@code @Configuration} bean definition resources need to be

 * imported, use the {@link ImportResource @ImportResource} annotation instead.

 *

 * @author Chris Beams

 * @author Juergen Hoeller

 * @since 3.0

 * @see Configuration

 * @see ImportSelector

 * @see ImportResource

 */

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Import {

    /**

     * {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}

     * or regular component classes to import.

     */

    Class<?>[] value();

}

关于Configuration和POJO,没什么好说的,就是简单的配置。这里说下ImportSelector和ImportBeanDefinitionRegistrar的作用(虽然开发过程中很少会使用到,但是Spring和Spring Boot的源码大面积使用了这个功能)。

ImportSelector

根据AnnotationMetadata(实质上是引入@Import注解的类的注解信息),来判断是否引入哪些配置类,通过字符串数组的方式返回配置类的全限定名。

DeferredImportSelector

ImportSelector的子接口,区别是,他会在所有的@Configuration类加载完成之后再加载返回的配置类。ImportSelector会在当前Configuration类加载之前去加载返回的配置类。

可以使用@Order注解或者Ordered接口来指定DeferredImportSelector的加载顺序。

并且提供了新的方法getImportGroup()用来跨DeferredImportSelector实现自定义Configuration的加载顺序。

ImportBeanDefinitionRegistrar

根据AnnotationMetadata(实质上是引入@Import注解的类的注解信息), 来注册BeanDenfinition,通过BeanDefinitionRegistry实例的register可以注册BeanDefinition。

三个接口的使用例子在文章最后面。

@ImportResource

和@Import类似,区别就是@ImportResource导入的是配置文件。

同样源码如下

/**

 * Indicates one or more resources containing bean definitions to import.

 *

 * <p>Like {@link Import @Import}, this annotation provides functionality similar to

 * the {@code <import/>} element in Spring XML. It is typically used when designing

 * {@link Configuration @Configuration} classes to be bootstrapped by an

 * {@link AnnotationConfigApplicationContext}, but where some XML functionality such

 * as namespaces is still necessary.

 *

 * <p>By default, arguments to the {@link #value} attribute will be processed using a

 * {@link org.springframework.beans.factory.groovy.GroovyBeanDefinitionReader GroovyBeanDefinitionReader}

 * if ending in {@code ".groovy"}; otherwise, an

 * {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader XmlBeanDefinitionReader}

 * will be used to parse Spring {@code <beans/>} XML files. Optionally, the {@link #reader}

 * attribute may be declared, allowing the user to choose a custom {@link BeanDefinitionReader}

 * implementation.

 *

 * @author Chris Beams

 * @author Juergen Hoeller

 * @author Sam Brannen

 * @since 3.0

 * @see Configuration

 * @see Import

 */

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

@Documented

public @interface ImportResource {

    /**

     * Alias for {@link #locations}.

     * @see #locations

     * @see #reader

     */

    @AliasFor("locations")

    String[] value() default {};

    /**

     * Resource locations from which to import.

     * <p>Supports resource-loading prefixes such as {@code classpath:},

     * {@code file:}, etc.

     * <p>Consult the Javadoc for {@link #reader} for details on how resources

     * will be processed.

     * @since 4.2

     * @see #value

     * @see #reader

     */

    @AliasFor("value")

    String[] locations() default {};

    /**

     * {@link BeanDefinitionReader} implementation to use when processing

     * resources specified via the {@link #value} attribute.

     * <p>By default, the reader will be adapted to the resource path specified:

     * {@code ".groovy"} files will be processed with a

     * {@link org.springframework.beans.factory.groovy.GroovyBeanDefinitionReader GroovyBeanDefinitionReader};

     * whereas, all other resources will be processed with an

     * {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader XmlBeanDefinitionReader}.

     * @see #value

     */

    Class<? extends BeanDefinitionReader> reader() default BeanDefinitionReader.class;

}

default和locations作用相同,都是用来指定配置文件的位置。

关于reader,一般情况下们不需要指定这个属性,默认情况,如果配置文件是.groovy结尾的将会使用GroovyBeanDefinitionReader来进行解析,其他的将会使用XmlBeanDefinitionReader来进行解析。一般需要显示的指定reader的情况是开发者需要实现自己的配置文件方式,比如说自己实现了一个JSONBeanDefinitionReader用来解析JSON的配置文件以达到可以将Spring以JSON的方式进行配置(开发中使用较少)。

一般情下,Spring还是推荐使用@Import而不是@ImportResource。

附页-@Import的测试代码

public class Main {

    public static void main(String[] args) {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

        context.register(Config.class, Config1.class);

        context.refresh();

    }

    public static class BeanDemo0 {

        private Integer id;

        private String name;

        public Integer getId() {

            return id;

        }

        public void setId(Integer id) {

            this.id = id;

        }

        public String getName() {

            return name;

        }

        public void setName(String name) {

            this.name = name;

        }

    }

    @Configuration

    @Import({MyImportSelector.class, MyImportBeanDefinitionRegistrar.class, MyImportSelector1.class})

    public static class Config {

        @Bean

        public BeanDemo0 beanDemo() {

            System.out.println("----beanDemo----");

            BeanDemo0 beanDemo0 = new BeanDemo0();

            beanDemo0.setId(1);

            beanDemo0.setName("123");

            return beanDemo0;

        }

    }

    @Configuration

    public static class Config_1 {

        @Bean

        public BeanDemo0 beanDemo_1() {

            System.out.println("----beanDemo_1----");

            BeanDemo0 beanDemo0 = new BeanDemo0();

            beanDemo0.setId(1);

            beanDemo0.setName("123");

            return beanDemo0;

        }

    }

    @Configuration

    public static class Config0 {

        @Bean

        public BeanDemo0 beanDemo0() {

            System.out.println("----beanDemo0----");

            BeanDemo0 beanDemo0 = new BeanDemo0();

            beanDemo0.setId(1);

            beanDemo0.setName("123");

            return beanDemo0;

        }

    }

    @Configuration

    public static class Config00 {

        @Bean

        public BeanDemo0 beanDemo00() {

            System.out.println("----beanDemo00----");

            BeanDemo0 beanDemo0 = new BeanDemo0();

            beanDemo0.setId(1);

            beanDemo0.setName("123");

            return beanDemo0;

        }

    }

    @Configuration

    public static class Config000 {

        @Bean

        public BeanDemo0 beanDemo000() {

            System.out.println("----beanDemo000----");

            BeanDemo0 beanDemo0 = new BeanDemo0();

            beanDemo0.setId(1);

            beanDemo0.setName("123");

            return beanDemo0;

        }

    }

    @Configuration

    public static class Config0000 {

        @Bean

        public BeanDemo0 beanDemo0000() {

            System.out.println("----beanDemo0000----");

            BeanDemo0 beanDemo0 = new BeanDemo0();

            beanDemo0.setId(1);

            beanDemo0.setName("123");

            return beanDemo0;

        }

    }

    @Configuration

    @Import({MyImportSelector2.class})

    public static class Config1 {

        @Bean

        public BeanDemo0 beanDemo1() {

            System.out.println("----beanDemo1----");

            BeanDemo0 beanDemo0 = new BeanDemo0();

            beanDemo0.setId(1);

            beanDemo0.setName("123");

            return beanDemo0;

        }

    }

    @Configuration

    public static class Config2 {

        @Bean

        public BeanDemo0 beanDemo2() {

            System.out.println("----beanDemo2----");

            BeanDemo0 beanDemo0 = new BeanDemo0();

            beanDemo0.setId(1);

            beanDemo0.setName("123");

            return beanDemo0;

        }

    }

    public static class MyImportSelector implements ImportSelector {

        /**

         * AnnotationMetadata表示了使用@Import引入MyImportSelector的类的注解meta信息。

         * 在这个例子中,annotationMetadata可以获取到Config类上的注解详细信息。

         */

        @Override

        public String[] selectImports(AnnotationMetadata annotationMetadata) {

            /*System.out.println("class name --> " + annotationMetadata.getClass().getSimpleName());

            System.out.println("className --> " + annotationMetadata.getClassName());

            Set<String> annotationTypes = annotationMetadata.getAnnotationTypes();

            System.out.println(annotationTypes);*/

//            System.out.println("" + annotationMetadat);

            System.out.println("----MyImportSelector-----");

            return new String[] {"cn.xtt.study.spring.imports.Main.Config_1"};

        }

    }

    /**

     * after all config

     */

    public static class MyImportSelector1 implements DeferredImportSelector {

        @Override

        public Class<? extends Group> getImportGroup() {

            return MyGroup.class;

        }

        @Override

        public String[] selectImports(AnnotationMetadata annotationMetadata) {

            System.out.println("----DeferredImportSelector1-----");

            return new String[]{"cn.xtt.study.spring.imports.Main.Config0", "cn.xtt.study.spring.imports.Main.Config00"};

        }

    }

    public static class MyImportSelector2 implements DeferredImportSelector {

        @Override

        public Class<? extends Group> getImportGroup() {

            return MyGroup.class;

        }

        @Override

        public String[] selectImports(AnnotationMetadata annotationMetadata) {

            System.out.println("----DeferredImportSelector2-----");

            return new String[]{"cn.xtt.study.spring.imports.Main.Config000", "cn.xtt.study.spring.imports.Main.Config0000"};

        }

    }

    public static class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

        @Override

        public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {

            System.out.println("----MyImportBeanDefinitionRegistrar----");

            /*System.out.println(annotationMetadata);

            System.out.println("class name --> " + annotationMetadata.getClass().getSimpleName());

            System.out.println("className --> " + annotationMetadata.getClassName());

            System.out.println(registry);

            System.out.println("registry name " + registry.getClass().getSimpleName());*/

            registry.registerBeanDefinition("config2", new RootBeanDefinition(Config2.class));

        }

    }

    private static class MyGroup implements DeferredImportSelector.Group {

        private List<Entry> entries = new ArrayList<>(2);

        @Override

        public void process(AnnotationMetadata metadata, DeferredImportSelector selector) {

            for (String configClassName : selector.selectImports(metadata)) {

                entries.add(new Entry(metadata, configClassName));

            }

            entries.sort(new Comparator<Entry>() {

                @Override

                public int compare(Entry o1, Entry o2) {

                //按照配置类,全限定名的长度,从名称长的开始加载

                    return o2.getImportClassName().length() - o1.getImportClassName().length();

//                    return o1.getImportClassName().length() - o2.getImportClassName().length();

                }

            });

        }

        @Override

        public Iterable<Entry> selectImports() {

            return entries;

        }

    }

}

运行结果:

----MyImportSelector-----  

----DeferredImportSelector1-----  

----DeferredImportSelector2-----  

----MyImportBeanDefinitionReistrar----  

----beanDemo_1----  

----beanDemo----  

----beanDemo1----  

----beanDemo0000----  

----beanDemo000----  

----beanDemo00----  

----beanDemo0----  

----beanDemo2----  

原文:https://blog.csdn.net/xt8469/article/details/82260091 

相关推荐