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 兩個類的實例。