SpringBoot @Import 詳解

SpringBoot 的 @Import 用於將指定的類實例注入之Spring IOC Container中。 

SpringBoot 提供了 三種使用 @Import 將 類實例注入至 Spring IOC Container中 的實例。
  • 直接注入
  • 實現 ImportBeanDefinitionRegistrar 接口 注入
  • 實現 ImportSelector 注入
  • 直接注入

    • Broker.java(無任何屬性和實現)

      package com.springBoot.entrance.importBean.direct;
      
      public class Broker {
      
      }
    • Customer.java(無任何屬性和實現)

      package com.springBoot.entrance.importBean.direct;
      
      public class Customer {
      
      }
    • ImportDirect.java

      package com.springBoot.entrance.importBean.direct;
      
      import org.springframework.context.annotation.Import;
      import org.springframework.stereotype.Component;
      
      
      @Component
      @Import({Customer.class,Broker.class})
      /**
       *使用Import 將指定的類的實例注入至Spring 容器中
       */
      public class ImportDirect {
      
      }

      代碼解讀:使用 @Import({Customer.class,Broker.class}) 後 Customer 和 Broker類的實例將會被注入之Spring IOC Container中

    • App.java

      //import Direct 使用import 直接將指定的類實例注入至Spring 容器中
              System.out.println(context.getBean(ImportDirect.class));
              System.out.println(context.getBean(Customer.class));
              System.out.println(context.getBean(Broker.class));
    • 結果 
      這裏寫圖片描述


  • 實現 ImportBeanDefinitionRegistrar 接口 注入

  • Forwards.java(無任何屬性和實現)

    package com.springBoot.entrance.importBean.indirectImportBeanDefinitionRegistrar;
    
    public class Forwards {
    
    }
  • Security.java(無任何屬性和實現)

    package com.springBoot.entrance.importBean.indirectImportBeanDefinitionRegistrar;
    
    public class Security {
    
    }
  • MyImportBeanDefinitionRegistrar.java

    package com.springBoot.entrance.importBean.indirectImportBeanDefinitionRegistrar;
    
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
    import org.springframework.core.type.AnnotationMetadata;
    
    /**
     * registerBeanDefinitions 方法中的參數 BeanDefinitionRegistry 可以往Spring IOC Container 中動態地裝配Bean
     */
    public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    
            //手動注入 Forwards 類的實例
            BeanDefinitionBuilder beanDef_forwards = BeanDefinitionBuilder.rootBeanDefinition(Forwards.class);
            registry.registerBeanDefinition("forwards", beanDef_forwards.getBeanDefinition());
    
            //手動注入 Security類的實例
            BeanDefinitionBuilder beanDef_security = BeanDefinitionBuilder.rootBeanDefinition(Security.class);
            registry.registerBeanDefinition("security", beanDef_security.getBeanDefinition());
        }
    
    }
  • App.java

    @Import(MyImportBeanDefinitionRegistrar.class)
    @Configuration
    public class App {
    
    
        public static void main(String[] args) throws Exception {
            ConfigurableApplicationContext context = SpringApplication.run(App.class, args);
    
            //實現ImportBeanDefinitionRegistrar 實現Bean的注入
            System.out.println(context.getBean(MyImportBeanDefinitionRegistrar.class));
            System.out.println(context.getBean(Forwards.class));
            System.out.println(context.getBean(Security.class));
    
        }
    
    
    }
  • 實現 ImportSelector 注入

  • Market.java(無任何屬性或實現)

    package com.springBoot.entrance.importBean.indirectImportSelector;
    
    public class Market {
    
    }
  • Sales.java(無任何屬性或實現)

    package com.springBoot.entrance.importBean.indirectImportSelector;
    
    public class Sales {
    
    }
  • EnableLogInfo.java

    package com.springBoot.entrance.importBean.indirectImportSelector;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    import org.springframework.context.annotation.Import;
    
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Documented
    @Import(MyImportSelector.class)
    /**
     *自定義Enable*
     *1.
     */
    public @interface EnableLogInfo {
    
        String[] name();
    
    
    }
  • MyImportSelector.java

    package com.springBoot.entrance.importBean.indirectImportSelector;
    
    import org.springframework.context.annotation.Import;
    import org.springframework.context.annotation.ImportSelector;
    import org.springframework.core.type.AnnotationMetadata;
    import org.springframework.stereotype.Component;
    
    @Component
    @Import(value = { MyImportSelector.class })
    @EnableLogInfo(name="onlySale")
    /**
     * Bean的批量注入 使用自定義 ImportSelector 須實現 ImportSelector
     * 接口,返回值必須是class全稱測集合,該集合內的所有類都將被Spring IOC容器統一管理
     */
    public class MyImportSelector implements ImportSelector {
    
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
    
            System.out.println(importingClassMetadata.getAnnotationAttributes(EnableLogInfo.class.getName()).toString().contains("onlySale"));
    
            //獲取自定的@EnableLogInfo 信息 如果包含 onlySale 則只注入Sales class 否則 注入 Sales 和 Market 兩個類
            if (importingClassMetadata.getAnnotationAttributes(EnableLogInfo.class.getName()) != null
                    && importingClassMetadata.getAnnotationAttributes(EnableLogInfo.class.getName()).toString().contains("onlySale")) {
    
                return new String[] {Sales.class.getName() };
            }
    
            // 將指定的類
            return new String[] { Market.class.getName(), Sales.class.getName() };
        }
    
    }

    代碼解讀:此處使用了@Import註解和實現了 ImportSelector 來注入Bean

    代碼邏輯:通過 實現 ImportSelector 獲得 importingClassMetadata 對象,然後再由 importingClassMetadata 獲得 我們自定的@EnableLogInfo 中的 值,如果 該值包含 onlySale 則 我們只裝配Sale 類實例,否則 裝配 Sale 和Market 兩個類的實例。











發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章