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 两个类的实例。