首页 Import注解
文章
取消

Import注解

@Import的定义

@Import的源码

1
2
3
4
5
6
7
8
package org.springframework.context.annotation;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
  Class<?>[] value();
}

注解内部只有一个默认属性,并且类型是Class对象数组类型,实际上@Import就是用来把需要定义为Bean的类导入到IOC容器里面。

导入普通类

如何导入

  1. @Import应该标记在@SpringBootApplication(启动类)、@Configuration(配置类)、@Component(组件类)对应的类上。

@RestController、@Service、@Repository都属于@Component

  1. 在默认属性中指定需要导入的类的class对象

示例:

1
2
3
4
5
6
7
@SpringBootApplication
@Import(ImportBean.class) // 通过@Import注解把ImportBean添加到IOC容器里面去
public class MyBatisApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyBatisApplication.class, args);
    }
}

引入配置类(@Configuration修饰的类)

达到的效果

能够使得配置类生效,当然在启动类的根目录或子目录下,@Configuration标注的类会自动生效,使用@Import的场景往往是不在启动类根目录下,比如自定义Starter会经常用到

如何使用

与导入普通时一样,依然需要满足第一点,在第二点时就导入对应的配置类的class对象

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Configuration(proxyBeanMethods = false)
@Import({  // import了两个
        XXXDataConfiguration.XXXPartOneConfiguration.class,
        XXXDataConfiguration.XXXPartTwoConfiguration.class
})
public class XXXDataAutoConfiguration {
}

public class XXXDataConfiguration {
    @Configuration(proxyBeanMethods = false)
    static class XXXPartOneConfiguration {
        @Bean
        @ConditionalOnMissingBean
        public BeanForIoc beanForIoc() {
            return new BeanForIoc();
        }
    }
    @Configuration(proxyBeanMethods = false)
    static class XXXPartTwoConfiguration {
        /**
         * 省略了@Bean的使用
         */
    }

}

导入ImportSelector的实现类

达到的效果

可以把ImportSelector接口selectImports()方法返回的Class名称都定义为bean。

ImportSelector接口源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public interface ImportSelector {

    /**
     * Select and return the names of which class(es) should be imported based on
     * the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
     * @return the class names, or an empty array if none
     */
    String[] selectImports(AnnotationMetadata importingClassMetadata);

    @Nullable
    default Predicate<String> getExclusionFilter() {
        return null;
    }

}

在实现类中,selectImports()会返回需要导入容器中的类名

静态导入

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
 * XXXConfigurationSelector一定要配合@Import使用
 */
public class XXXConfigurationImportSelector implements ImportSelector {
    @Override
    @NonNull
    public String[] selectImports(@NonNull AnnotationMetadata importingClassMetadata) {
        // 把XXX对应的类,定义为Bean
        return new String[]{XXX.class.getName()};
    }
}

/**
 * 注意 @Import(XXXConfigurationImportSelector.class)
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(XXXConfigurationImportSelector.class)
public @interface EnableXXX {
}

@SpringBootApplication
@EnableXXX // 使之生效
public class MyBatisApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyBatisApplication.class, args);
    }
}
本文由作者按照 CC BY 4.0 进行授权