`
y806839048
  • 浏览: 1127091 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

@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 

 

 

 

 

 

分享到:
评论

相关推荐

    springBoot自动装配原理以及starter技术.pdf

    它负责解析`@Configuration`、`@ComponentScan`、`@ImportResource`等注解,构建BeanDefinition,并将它们添加到BeanDefinitionRegistry中。 5. **内部类与元数据** `@Import`还可以用于导入内部类,这在处理复杂...

    spring加载多个配置文件

    在Spring框架中,加载多个配置文件是常见的需求,特别是在大型项目中,为了保持代码的整洁和模块化,通常...通过理解并熟练运用这些加载机制,开发者可以更好地组织和管理项目中的配置,提高代码的可维护性和可扩展性。

    SpringBoot中必须掌握的27个注解.docx

    - **用途**:与`@Import`类似,但`@ImportResource`用于导入XML配置文件到Spring容器中。这种方式使得在纯注解配置之外,仍然可以利用XML文件进行配置。 ##### 6、@Component - **用途**:`@Component`是一个通用的...

    跟我学Spring3(12.3)零配置之注解实现Bean定

    7. `@Import`和`@ImportResource`:`@Import`可以用来导入其他配置类,而`@ImportResource`则可以导入XML配置文件,这样你可以在注解配置和XML配置之间自由切换。 8. 配合JSR 330标准的注解,如`@Inject`和`@Named`...

    spring注解开发.zip

    15. `@Import`和`@ImportResource`:`@Import`用于导入其他配置类,`@ImportResource`用于导入XML配置文件。 通过理解并熟练运用这些注解,Spring开发者可以更加高效地构建应用程序,减少XML配置,提升代码可读性...

    如何加载jar包中的spring配置文件

    加载jar包中的Spring配置文件需要对Spring的类路径加载机制有深入理解。通过`ClassPathResource`,我们可以定位并加载jar包内的配置,然后应用到`ApplicationContext`。在SSM整合的项目中,正确地加载这些配置文件...

    SpringBoot中必须掌握的27个注解.pdf

    5. **@ImportResource**:与@Import类似,但导入的是XML配置文件,将XML配置中的bean定义加入到Spring容器。 6. **@Component**:这是Spring的一个元注解,可以标记其他类注解,如@Controller、@Service和@...

    Spring中Quartz的配置(守护进程)(本人亲自测试)

    如果你使用了`quartz_test`目录下的测试资源,那么这个目录可能包含了用于测试的配置文件或代码示例,可以帮助你更好地理解和验证Quartz在Spring中的配置和运行情况。 总之,Spring与Quartz的集成提供了强大的定时...

    第十八章 Spring 注解(Annotations)1

    - **装配注解**:@ImportResource用于导入XML配置,@Import可以导入Configuration类,@ComponentScan扫描指定包下的注解类。 - **依赖注入注解**:@Autowired自动装配bean,@Qualifier提供更精确的依赖选择。 3. ...

    springboot注解.docx

    10. **@ImportResource**:用于加载XML配置文件,尽管Spring Boot提倡无XML配置,但在需要的情况下,仍可通过此注解引入XML配置。 11. **@Autowired**:自动装配bean,按照类型匹配并注入,可以用于字段、方法或...

    Spring Boot技术知识点:如何读取不同路径里的applicationContext.xml配置文件4

    - **文档**:清晰记录使用了哪些XML配置,以及它们在项目中的作用,便于其他开发者理解和维护。 总的来说,虽然Spring Boot推崇的是Java和YAML配置,但通过上述方法,我们仍然可以灵活地在项目中读取和使用XML配置...

    springboot-dubbo-demo-xml.zip

    首先,我们要理解SpringBoot和Dubbo的基本概念。SpringBoot简化了Spring应用的初始搭建以及开发过程,它提供了自动配置、起步依赖、内嵌Web服务器等特性,使得开发更加高效。而Dubbo是阿里巴巴开源的一款高性能、轻...

    在Spring Boot中加载XML配置的完整步骤

    理解`@ImportResource`注解,它实际上是在Spring的`spring-context`模块中定义的,用于在Spring容器启动时加载XML配置文件。`ImportResource`内部实现了`BeanDefinitionReader`接口,该接口负责读取XML文件并将其...

    springboot[1]-多模块共用配置文件.zip

    若要使多模块项目中的其他模块能够识别并加载`common-config`模块的配置,可以使用`@ImportResource`注解或者`@Import`导入配置类。 - **配置类**:如果配置较多,可以创建一个配置类,通过`@...

    Spring笔记(面试题)md

    ### Spring框架概述与特点 #### 1. 什么是Spring框架? Spring框架是一个开源的企业级Java应用框架,也是目前最流行的Java EE开发框架之一。...希望这些内容能帮助您更好地理解和掌握Spring框架的相关知识。

    spring-code-config-reference

    文档还提到了一系列用于Code Config的属性,如`Configuration`、`Definition`、`DependsOn`、`Import`、`ImportResource`、`Lazy`和`Scope`属性,它们分别用于标记配置类、定义bean、指定依赖关系、导入其他配置、...

    spring资料3

    ApplicationContext支持通过`@ImportResource`注解或XML配置中的`&lt;import&gt;`标签将多个配置文件合并。此外,该视频可能还会讲解如何实现国际化,即I18N,Spring提供了MessageSource接口,可以加载不同语言的资源文件...

Global site tag (gtag.js) - Google Analytics