<optgroup id="ygyw8"></optgroup>
<optgroup id="ygyw8"></optgroup><optgroup id="ygyw8"></optgroup>
  • <sup id="ygyw8"></sup>
  • 千鋒扣丁學堂Java培訓之Spring中@Import用法以及ImportAware接口

    2019-10-08 14:25:15 7248瀏覽

    今天千鋒扣丁學堂Java培訓老師給大家分享一篇關于Spring中@Import的各種用法以及ImportAware接口詳解,文中通過示例代碼介紹的非常詳細,下面我們一起來看一下吧。



    @Import注解

    @Import注解提供了和XML中<import/>元素等價的功能,實現導入的一個或多個配置類。@Import即可以在類上使用,也可以作為元注解使用。

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Import {
     
      /**
       * {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
       * or regular component classes to import.
       */
      Class<?>[] value();
     
    }

    注解中只有一個value();。支持導入@Configuration標注的配置類,實現ImportSelector接口的類、實現ImportBeanDefinitionRegistrar接口的類和普通的@component類。

    作為元注解使用

    @Import可以作為元注解使用,可以在@Import的繼承上封裝一層。我的理解是,這樣做不會對外(使用方)暴露我內部的具體實現細節。

    舉個例子:例如@EnableAspectJAutoProxy注解。

    @Import(AspectJAutoProxyRegistrar.class)
    public @interface EnableAspectJAutoProxy {

    @EnableAspectJAutoProxy就是被@Import這個元注解所標志了,我們(程序員)通過使用@EnableAspectJAutoProxy來開啟AspectJAutoProxy,而Spring底層是通過@Import導入相應的配置類來實現的。

    導入實現ImportSelector接口的類

    先來看一下ImportSelector接口,該接口中只有一個方法:

    public interface ImportSelector {
      String[] selectImports(AnnotationMetadata importingClassMetadata);
    }

    ImportSelector,輸入選擇器。該接口就是用來根據給定的條件,選擇導入哪些配置類。

    舉個例子:例如@EnableTransactionManagement注解。

    @Import(TransactionManagementConfigurationSelector.class)
    public @interface EnableTransactionManagement {

    在@EnableTransactionManagement注解中使用了@Import(TransactionManagementConfigurationSelector.class)注解,其中TransactionManagementConfigurationSelector類就是實現了ImportSelector接口。

    public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
      @Override
      protected String[] selectImports(AdviceMode adviceMode) {
        switch (adviceMode) {
          case PROXY:
            return new String[] {AutoProxyRegistrar.class.getName(),
                ProxyTransactionManagementConfiguration.class.getName()};
          case ASPECTJ:
            return new String[] {
                TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
          default:
            return null;
        }
      }
    }

    方法的內部實現邏輯也很簡單,就是根據不同的AdviceMode導入不同的配置類,來實現事務管理。

    導入實現ImportBeanDefinitionRegistrar接口的類

    ImportBeanDefinitionRegistrar接口中也只有一個方法:

    public interface ImportBeanDefinitionRegistrar {
      void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
    }

    該接口允許我們根據所給的注解元數據,按需注冊額外的BeanDefinition。

    舉個例子:例如@EnableAspectJAutoProxy注解。

    @Import(AspectJAutoProxyRegistrar.class)
    public @interface EnableAspectJAutoProxy {

    @EnableAspectJAutoProxy注解引入了AspectJAutoProxyRegistrar.class類,這個類就是實現了ImportBeanDefinitionRegistrar接口。

    classAspectJAutoProxyRegistrarimplementsImportBeanDefinitionRegistrar{

      @Override
      public void registerBeanDefinitions(
          AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
     
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
     
        AnnotationAttributes enableAspectJAutoProxy =
            AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy != null) {
          if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
          }
          if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
          }
        }
      }
    }

    registerBeanDefinitions中調用了AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);方法,這個方法就是在往傳入的BeanDefinitionRegistryregistry中注冊BeanDefinition。注冊了BeanDefinition之后,Spring就會去實例化這個Bean,從而達到AspectJAutoProxy作用。

    導入@Configuration類

    這次@Import最常見是使用方法。我們可以拆分配置類,然后在程序中按需導入相應的配置。

    舉個例子:例如@EnableRetry注解。使用這個注解可以開啟retry功能。

    @EnableAspectJAutoProxy(proxyTargetClass = false)
    @Import(RetryConfiguration.class)
    public @interface EnableRetry {

    其內部就是導入了RetryConfiguration這個配置類。

    ImportAware接口

    ImportAware接口是需要和@Import一起使用的。在@Import作為元注解使用時,通過@Import導入的配置類如果實現了ImportAware接口就可以獲取到導入該配置類接口的數據配置。有點繞,我們直接上代碼。

    舉個例子:@EnableAsync注解。

    @Import(AsyncConfigurationSelector.class)
    public @interface EnableAsync {
    //AsyncConfigurationSelector源碼
    public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {
     
      private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
          "org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";
      @Override
      @Nullable
      public String[] selectImports(AdviceMode adviceMode) {
        switch (adviceMode) {
          case PROXY:
            return new String[] {ProxyAsyncConfiguration.class.getName()};
          case ASPECTJ:
            return new String[] {ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME};
          default:
            return null;
        }
      }
    }

    默認情況下使用AdviceMode為PROXY,導入了ProxyAsyncConfiguration類。

    @Configuration
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public class ProxyAsyncConfiguration extends AbstractAsyncConfiguration {
     
      @Bean(name = TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME)
      @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
      public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
        Assert.notNull(this.enableAsync, "@EnableAsync annotation metadata was not injected");
        AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();
        Class<? extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation");
        if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) {
          bpp.setAsyncAnnotationType(customAsyncAnnotation);
        }
        if (this.executor != null) {
          bpp.setExecutor(this.executor);
        }
        if (this.exceptionHandler != null) {
          bpp.setExceptionHandler(this.exceptionHandler);
        }
        bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass"));
        bpp.setOrder(this.enableAsync.<Integer>getNumber("order"));
        return bpp;
      }
    }

    在ProxyAsyncConfiguration的asyncAdvisor方法中需要獲取到@EnableAsync上的一些設置值,例如:this.enableAsync.getBoolean("proxyTargetClass"),this.enableAsync.<Integer>getNumber("order")。

    this.enableAsync是其父類AbstractAsyncConfiguration的屬性。AbstractAsyncConfiguration實現了ImportAware接口,從而就可以獲取到@EnableAsync上的信息了。

    // AbstractAsyncConfiguration#setImportMetadata 源碼
    public void setImportMetadata(AnnotationMetadata importMetadata) {
      this.enableAsync = AnnotationAttributes.fromMap(
          importMetadata.getAnnotationAttributes(EnableAsync.class.getName(), false));
      if (this.enableAsync == null) {
        throw new IllegalArgumentException(
            "@EnableAsync is not present on importing class " + importMetadata.getClassName());
      }
    }

    可能這個例子有點復雜的,還有一個稍微簡單一點的例子:EnableRedisHttpSession。關于這個,讀者可以自己去看一下源碼debug學習一下。

    以上就是關于千鋒扣丁學堂Java培訓之Spring中@Import用法以及ImportAware接口的全部內容,希望對大家的學習有所幫助,想要學好Java開發小編給大家推薦口碑良好的扣丁學堂,扣丁學堂有專業老師制定的Java學習路線圖輔助學員學習,此外還有與時俱進的Java課程體系和Java視頻教程供大家學習,想要學好Java開發技術的小伙伴快快行動吧??鄱W堂Java技術交流群:850353792。


                              JavaEE/微服務/源碼解析/分布式/企業級架構【VIP體驗課】


         【關注微信公眾號獲取更多學習資料】        【掃碼進入JavaEE/微服務VIP免費公開課】  



    查看更多關于“Java開發資訊”的相關文章>>

    標簽: Java培訓 Java視頻教程 Java多線程 Java面試題 Java學習視頻 Java開發

    熱門專區

    暫無熱門資訊

    課程推薦

    微信
    微博
    15311698296

    全國免費咨詢熱線

    郵箱:codingke@1000phone.com

    官方群:148715490

    北京千鋒互聯科技有限公司版權所有   北京市海淀區寶盛北里西區28號中關村智誠科創大廈4層
    京ICP備2021002079號-2   Copyright ? 2017 - 2022
    返回頂部 返回頂部
    成人综合伊人五月婷久久,公交上配合陌生人弄嗯啊好湿,色欲综合久久躁天天躁,天天操天天干,精品人妻系列无码人妻免费视频,太粗太深了太紧太爽了动态图
    <optgroup id="ygyw8"></optgroup>
    <optgroup id="ygyw8"></optgroup><optgroup id="ygyw8"></optgroup>
  • <sup id="ygyw8"></sup>