javascript
@mapperscan注解_Spring的@Import注解详解
首先看下@Import的javadoc文檔:
Provides functionality equivalent to the <import/> element in Spring XML. Allows for importing @Configuration classes, ImportSelector and ImportBeanDefinitionRegistrar implementations, as well as regular component classes (as of 4.2; analogous to AnnotationConfigApplicationContext.register). @Bean definitions declared in imported @Configuration classes should be accessed by using @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 @Configuration class methods. May be declared at the class level or as a meta-annotation.簡單翻譯一下,這里面說了3個點(diǎn):
(1)@Import就是用來向容器中導(dǎo)入bean的,導(dǎo)入的方式有三種:導(dǎo)入@Configuration、導(dǎo)入ImportSelector、導(dǎo)入ImportBeanDefinitionRegistrar。
(2)被@Import的類是被加載到了Spring容器當(dāng)中,因此無論是類本身還是類里面用@Bean注解定義的bean都可以被@Autowired注入。
(3)@Import可以加在類上面,也可以作為元注解加在注解上面
下面就來分別舉例說明下。
1.導(dǎo)入@Configuration舉例
//這是個普通的類 public class Service1 {public Service1(){System.out.println("Service1");} } //這是個配置類 @Configuration public class DemoConfig {@Beanpublic Service2 service2(){return new Service2();} } @SpringBootApplication //這樣可以導(dǎo)入Service1和Service2這兩個Bean @Import({Service1.class, DemoConfig.class}) public class ImportDemoApplication {public static void main(String[] args) {SpringApplication.run(ImportDemoApplication.class, args);} }2.導(dǎo)入ImportSelector舉例
public class DemoImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {//這里返回bean的完整的名字return new String[]{"com.github.xjs.importdemo.service.Service3"};} } @SpringBootApplication //這樣就可以導(dǎo)入Service3這個bean @Import({DemoImportSelector.class}) public class ImportDemoApplication {public static void main(String[] args) {SpringApplication.run(ImportDemoApplication.class, args);} }3.導(dǎo)入ImportBeanDefinitionRegistrar舉例
public class DemoRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {//可以直接向容器注冊beanGenericBeanDefinition bd = new GenericBeanDefinition();bd.setBeanClass(Service4.class);registry.registerBeanDefinition("service4", bd);} } @SpringBootApplication //這樣就可以導(dǎo)入Service4這個bean @Import({DemoRegistrar.class}) public class ImportDemoApplication {public static void main(String[] args) {SpringApplication.run(ImportDemoApplication.class, args);} }4.@Import作為元注解使用舉例
因?yàn)?#64;Import可以作為元注解使用,因此可以用這個特性來做組件掃描,比如:
//首先定義一個用于掃描的注解,上面添加@Import元注解: @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) @Import({DemoImportSelector.class}) public @interface DemoScan {/*** 要掃描的根路徑* */String basePackage() default ""; }然后在啟動類或者配置類上添加這個注解:
@SpringBootApplication //首先添加這個注解 @DemoScan(basePackage="com.github.xjs") @Import({DemoImportSelector.class, DemoRegistrar.class}) public class ImportDemoApplication {public static void main(String[] args) {SpringApplication.run(ImportDemoApplication.class, args);} }無論是ImportSelector還是ImportBeanDefinitionRegistrar在回調(diào)中都可以使用AnnotationMetadata獲取@DemoScan里面的屬性:
public class DemoImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {//讀取DemoScan的屬性AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(DemoScan.class.getName()));String basePackage = annoAttrs.getString("basePackage");System.out.println("basePackage:"+basePackage);return new String[]{"com.github.xjs.importdemo.service.Service3"};} }拿到了要掃描的路徑如何去掃描可以參考上一篇如何去掃描Mapper接口的,在Spring的源碼中有大量的這種用法,比如:ServletComponentScan與ServletComponentScanRegistrar、MapperScan與MapperScannerRegistrar等等。
5.@Import解析的源碼
// org.springframework.context.annotation.ConfigurationClassParser: private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,Collection<SourceClass> importCandidates, boolean checkForCircularImports) {...for (SourceClass candidate : importCandidates) {if (candidate.isAssignable(ImportSelector.class)) {// Candidate class is an ImportSelector -> delegate to it to determine importsClass<?> candidateClass = candidate.loadClass();ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);ParserStrategyUtils.invokeAwareMethods(selector, this.environment, this.resourceLoader, this.registry);if (selector instanceof DeferredImportSelector) {this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);}else {String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);processImports(configClass, currentSourceClass, importSourceClasses, false);}}else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {// Candidate class is an ImportBeanDefinitionRegistrar ->// delegate to it to register additional bean definitionsClass<?> candidateClass = candidate.loadClass();ImportBeanDefinitionRegistrar registrar = BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);ParserStrategyUtils.invokeAwareMethods(registrar, this.environment, this.resourceLoader, this.registry);configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());}else {// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->// process it as an @Configuration classthis.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());processConfigurationClass(candidate.asConfigClass(configClass));}}... } }完整的源碼下載:
https://github.com/xjs1919/enumdemo 下的 import-demo
歡迎掃碼加關(guān)注:
總結(jié)
以上是生活随笔為你收集整理的@mapperscan注解_Spring的@Import注解详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: word 编辑域中的汉字_15条Word
- 下一篇: pywin32 获取窗口句柄_Excel