簡介
在平時看源碼或者很多配置類上面都會出現(xiàn)@Import注解,功能就是和Spring XML 里面 的 一樣. @Import注解是用來導入配置類或者一些需要前置加載的類.
源碼解析
導入配置的三種類型
@Import支持 三種方式 1.帶有@Configuration的配置類(4.2 版本之前只可以導入配置類,4.2版本之后 也可以導入 普通類) 2.ImportSelector 的實現(xiàn) 3.ImportBeanDefinitionRegistrar 的實現(xiàn)
源碼解釋
/**
* Indicates one or more {@link Configuration @Configuration} classes to import.
*
*功能類似XML 里面的 <import/> ,可以導入 @Configuration配置類,ImportSelector、
* ImportBeanDefinitionRegistrar 的實現(xiàn),4.2 版本之后可以導入普通類(類似AnnotationConfigApplicationContext#register
* )
* <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>May be declared at the class level or as a meta-annotation.
* 如需要引入XML或其他類型的文件,使用@ImportResource注解
* <p>If XML or other non-{@code @Configuration} bean definition resources need to be
* imported, use the {@link ImportResource @ImportResource} annotation instead.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
/**
* {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
* or regular component classes to import.
*/
Class<?>[] value();
}
測試例子
導入普通類
新建一個TestA
public class TestA {
public void fun(String str) {
System.out.println(str);
}
public void printName() {
System.out.println("類名 :" + Thread.currentThread().getStackTrace()[1].getClassName());
}
}
新建一個ImportConfig,在類上面加上@Configuration,加上@Configuration是為了能讓Spring 掃描到這個類,并且直接通過@Import引入TestA類
@Import({TestA.class})
@Configuration
public class ImportConfig {
}
測試結果
TestA 是一個普通的類,現(xiàn)在可以被@Autowired注釋然后調用,就直接說明已經被Spring 注入并管理了,普通的類都是需要先實例化
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ApplicationMain.class)
public class ImportAnnotionTest {
@Autowired
TestA testA;
@Test
public void TestA() {
testA.printName();
}
}
// 輸出
類名 :com.test.importdemo.TestA
導入帶有@Configuration的配置類
新建TestB
@Configuration
public class TestB {
public void fun(String str) {
System.out.println(str);
}
public void printName() {
System.out.println("類名 :" + Thread.currentThread().getStackTrace()[1].getClassName());
}
}
在ImportConfig.class里面直接引入TestB
@Import({TestA.class,TestB.class})
@Configuration
public class ImportConfig {
}
測試結果 TestB.class 的類上面已經有了@Configuration注解,本身就會配spring掃到并實例,@import引入帶有@Configuration的配置文件,是需要先實例這個配置文件再進行相關操作
@Autowired
TestB testB;
@Test
public void TestB(){
testB.printName();
}
通過ImportSelector 方式導入的類
新建TestC.class
public class TestC {
public void fun(String str) {
System.out.println(str);
}
public void printName() {
System.out.println("類名 :" + Thread.currentThread().getStackTrace()[1].getClassName());
}
}
新建SelfImportSelector.class 實現(xiàn)ImportSelector 接口,注入TestC.class
public class SelfImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.test.importdemo.TestC"};
}
}
ImportConfig上面引入SelfImportSelector.class
@Import({TestA.class,TestB.class,SelfImportSelector.class})
@Configuration
public class ImportConfig {
}
測試結果
@Autowired
TestC testC;
@Test
public void TestC() {
testC.printName();
}
通過 ImportBeanDefinitionRegistrar 方式導入的類
新建TestD.class
public class TestD {
public void fun(String str) {
System.out.println(str);
}
public void printName() {
System.out.println("類名 :" + Thread.currentThread().getStackTrace()[1].getClassName());
}
}
新建SelfImportBeanDefinitionRegistrar.class,實現(xiàn)接口ImportBeanDefinitionRegistrar,注入TestD.class
public class SelfImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition root = new RootBeanDefinition(TestD.class);
registry.registerBeanDefinition("testD", root);
}
}
ImportConfig類上加上導入SelfImportBeanDefinitionRegistrar.class
@Import({TestA.class,TestB.class,SelfImportSelector.class,
SelfImportBeanDefinitionRegistrar.class})
@Configuration
public class ImportConfig {
}
測試結果
@Autowired
TestD testD;
@Test
public void TestD() {
testD.printName();
}