Spring的@Import註解簡單介紹
阿新 • • 發佈:2020-10-27
Spring的@Import註解
作用
- 將沒有使用@Component註解的普通class加入到Spring容器, 由Spring管理
- 匯入一個Configuration類
- 通過實現了ImportSelector介面的類, 匯入多個class到Spring容器(SpringBoot的自動裝配@EnableAutoConfiguration)
- 通過實現ImportBeanDefinitionRegistrar介面的方式(MyBatis整合Spring: MapperScannerRegistrar.java和@MapperScan註解)
示例
1. 將普通Class加入到Spring容器
普通class
沒有使用@Component註解, 有一個例項方法.
/** * 一個普通的class, 沒有被打上{@link org.springframework.stereotype.Component}註解, 後續使用@Import匯入到Spring容器 * * @author rhyme */ @Slf4j public class ClassWithoutComponentAnnotation { public boolean methodA() { log.info("ClassWithoutComponentAnnotation物件的**例項方法**methodA被呼叫"); return true; } }
2. @Import Java Config
將該類也和上面一樣, 由@Import引入就行
@Configuration
public class ClassWithConfigurationAnnotation {
@Bean
public DemoClass demoClass() {
return new DemoClass();
}
}
3. 實現了ImportSelector介面的類, 匯入多個class到Spring容器
實現了ImportSelector介面的類
/** @author rhyme */ public class ClassImplementsImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String[] { "java.basic.demos.springannotation.Import.classimplementsimportselector.ClassA", "java.basic.demos.springannotation.Import.classimplementsimportselector.ClassB" }; } }
SpringBoot原始碼中使用了該方式
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
Class<?>[] exclude() default {};
/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
String[] excludeName() default {};
}
4. 實現ImportBeanDefinitionRegistrar介面的方式
實現了ImportBeanDefinitionRegistrar介面, 註冊自己的bean
/** @author rhyme */
public class ClassImplementImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition root = new RootBeanDefinition(ClassC.class);
registry.registerBeanDefinition("classC", root);
}
}
MyBatis整合Spring原始碼
/**
* A {@link ImportBeanDefinitionRegistrar} to allow annotation configuration of
* MyBatis mapper scanning. Using an @Enable annotation allows beans to be
* registered via @Component configuration, whereas implementing
* {@code BeanDefinitionRegistryPostProcessor} will work for XML configuration.
*
* @author Michael Lanyon
* @author Eduardo Macarron
*
* @see MapperFactoryBean
* @see ClassPathMapperScanner
* @since 1.2.0
*/
public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MapperScannerRegistrar.class)
public @interface MapperScan {
5. 使用@Import搭配@Configuration匯入普通class到Spring容器
/**
* @Import註解, 搭配@Configuration, 見ImportConfigTest.java<br>
* 1. 將沒有使用@Component註解的普通class加入到Spring容器, 由Spring管理<br>
* 2. 匯入一個Configuration類 <br>
* 3. 通過實現了ImportSelector介面的類, 匯入多個class到Spring容器(**SpringBoot的自動裝配@EnableAutoConfiguration**) <br>
* 4. 通過實現ImportBeanDefinitionRegistrar介面的方式(MyBatis整合Spring:MapperScannerRegistrar.java和@MapperScan註解)
*
* @author rhyme
*/
@Configuration
@Import({
ClassWithoutComponentAnnotation.class,
ClassWithConfigurationAnnotation.class,
ClassImplementsImportSelector.class,
ClassImplementImportBeanDefinitionRegistrar.class
})
public class ImportConfig {}
6. 測試
@RunWith(SpringRunner.class)
@SpringBootTest
public class ImportConfigTest {
@Autowired private ClassWithoutComponentAnnotation classWithoutComponentAnnotation;
@Autowired private DemoClass demoClass;
@Autowired private ClassA classA;
@Autowired private ClassB classB;
@Autowired private ClassC classC;
/** 通過@Autowired獲取@Import的類 */
@Test
public void importClass2SpringContainerTest() {
Assert.assertNotNull(classWithoutComponentAnnotation);
Assert.assertNotNull(demoClass);
Assert.assertNotNull(classA);
Assert.assertNotNull(classB);
Assert.assertNotNull(classC);
}
}