@Import可以導入bean或者@Configuration修飾的配置類。如果配置類在標准的springboot的包結構下,就是SpringbootApplication啟動類在包的根目錄下,配置類在子包下。就不需要使用@Import導入配置類,如果配置類在第三方的jar下,我們想要引入這個配置類,就需要@Import對其引入到工程中才能生效。因為這個時候配置類不再springboot默認的掃描范圍內。
另外,@Import 相當於Spring xml配置文件中的<import /> 標簽。
下面就看一看@Import的幾種用法:
使用方法一:導入普通類
1.1 把普通的類用@Import導入之后成為一個bean。這個類並未使用@Service、@Component將其創建為bean。
@Getter @Setter public class MySqlConn { private String driverClass = "xxxx"; private String url = "jdbc:mysql://localhost:3306/mydb"; private String userName = "root"; private String password = "root"; }
1.2 在springboot的啟動類@Import這個類,這個類就可以被其他類當做bean來引用。
@SpringBootApplication @Import({MySqlConn.class}) public class SpringBootApplication1 { public static void main(String[] args) { SpringApplication.run(SpringBootApplication1.class, args); } }
1.3 測試,定義一個controller來測試,調用這個通過@Import方式導入的bean
@RestController @RequestMapping("test") public class RestTestController { @Autowired private MySqlConn mySqlConn; @GetMapping("common") public String commonBean() { String jsonResult = ""; ObjectMapper mapper = new ObjectMapper(); try { jsonResult = mapper.writeValueAsString(mySqlConn); } catch (JsonProcessingException e) { e.printStackTrace(); } return jsonResult; } }
使用方法二:和@Configuration搭配使用
@Import被用來整合@Configuration注解中定義的bean配置。
2.1 定義一個配置類@Configuration,配置類中定義了一些bean。下面的代碼中可以看到我們定義的bean是MySqlServerBean。
@Configuration public class MySqlConfig { @Bean public MySqlServerBean getBean() { MySqlServerBean bean = new MySqlServerBean(); bean.setUserName("lyj"); return bean; } }
2.2 在啟動類中@import這個配置類:
@SpringBootApplication @Import(MySqlConfig.class) public class SpringBootApplication3 { public static void main(String[] args) { SpringApplication.run(SpringBootApplication3.class, args); } }
2.3 測試,定義一個controller,我們看到在controller中就可以直接使用在MySqlConfig中定義MySqlServerBean了。
@RestController @RequestMapping("test") public class RestTestController { @Autowired private MySqlServerBean mySqlServerBean; @GetMapping("mysql") public String mysql() { String jsonResult = ""; ObjectMapper mapper = new ObjectMapper(); try { jsonResult = mapper.writeValueAsString(mySqlServerBean); } catch (JsonProcessingException e) { e.printStackTrace(); } return jsonResult; } }
使用方法三:在配置類上導入
在配置類上通過@Import直接導入類,也可以被引用成bean。
3.1 定義一個普通的類
@Getter @Setter public class PoolBean { private String redisHost = "127.0.0.1"; private String redisPort = "6379"; private String redisDb = "0"; }
3.2 在配置類上導入這個類
@Configuration @Import({PoolBean.class}) public class RedisConfig { @Bean public RedisClusterBean getHost() { return new RedisClusterBean(); } }
3.3 測試,啟動項目,在controller直接引用這個PoolBean。
@SpringBootApplication public class SpringBootApplication2 { public static void main(String[] args) { SpringApplication.run(SpringBootApplication2.class, args); } }
@RestController @RequestMapping("test") public class RestTestController { @Autowired private PoolBean poolBean; @GetMapping("pool") public String poolBean() { String jsonResult = ""; ObjectMapper mapper = new ObjectMapper(); try { jsonResult = mapper.writeValueAsString(poolBean); } catch (JsonProcessingException e) { e.printStackTrace(); } return jsonResult; } }
使用方法四:和ImportSelector搭配使用
新建一個Maven工程,pom.xml的類型是jar,我們寫一個第三方的jar包,用來引用到我們的主工程中,進行ImportSelector的示例使用。工程結構大概如下圖:
4.1 在third-part功能中,我們先定義一個config
@Configuration public class AppConfig { @Bean public Student studentBean() { Student student = new Student(); student.setId(10); student.setName("王某"); return student; } }
4.2 自定義一個SpringStartSelector實現接口ImportSelector,BeanFactoryAware。重寫selectImports()方法和setBeanFactory()方法。這里在程序啟動的時候會先運行setBeanFactory()方法,我們可以在這里獲取到beanFactory。selectImports()方法回了了AppCoinfig的全類名。
public class SpringStartSelector implements ImportSelector, BeanFactoryAware { private BeanFactory beanFactory; @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { System.out.println("importingClassMetaData:" + importingClassMetadata); System.out.println("beanFactory:" + beanFactory); return new String[]{AppConfig.class.getName()}; } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } }
4.3 自定義一個注解EnableSpringStudy,在這個注解使用@Import()導入4.2中自定義的SpringStartSelector
@Retention(RetentionPolicy.RUNTIME) @Documented @Target(ElementType.TYPE) @Import(SpringStartSelector.class) public @interface EnableSpringStudy { }
4.4 完成之后我們把 third-part項目打成jar包,在主項目的pom文件中引入
<dependency> <groupId>com.win.world</groupId> <artifactId>third-part</artifactId> <version>1.0.0</version> </dependency>
4.5 主項目中在SpringBoot的啟動類上使用我們4.3中自定義的注解。然后測試我們能否獲取到AppConig中的bean。
@SpringBootApplication @EnableSpringStudy public class SpringBootApplication4 { public static void main(String[] args) { SpringApplication.run(SpringBootApplication4.class, args); } }
測試能否獲取到AppConfig中的bean
@RestController @RequestMapping("test") public class RestTestController { @Autowired private Student student; @GetMapping("selector") public String selector() { String jsonResult = ""; ObjectMapper mapper = new ObjectMapper(); try { jsonResult = mapper.writeValueAsString(student); } catch (JsonProcessingException e) { e.printStackTrace(); } return jsonResult; } }
使用方法五:和ImportBeanDefinitionRegistrar搭配使用
ImportBeanDefinitionRegistrar接口也是Spring的擴展點之一,它可以支持我們自己寫的代碼封裝成BeanDefinition對象;實現此接口的類回調postProcessBeanDefinitionRegistry方法,注冊到Spring容器中。把bean注入到Spring容器不止有@Service @Component 等注解方式,還可以實現此接口。下面看個例子:
5.1 我們先定義一個MyImportBeanDefinitionRegistrar類實現ImportBeanDefinitionRegistrar接口,並通過重寫registerBeanDefinitions()來定義一個bean
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar{ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { BeanDefinition beanDefinition = new GenericBeanDefinition(); beanDefinition.setBeanClassName(PoolBean.class.getName()); MutablePropertyValues property = beanDefinition.getPropertyValues(); property.addPropertyValue("redisHost", "localhost"); property.addPropertyValue("redisPort", "6377"); //這里注冊bean registry.registerBeanDefinition("poolBean", beanDefinition); } }
5.2 定義一個配置類,@Import導入5.1的自定義類
@Configuration @Import(MyImportBeanDefinitionRegistrar.class) public class RegistrarConfig { }
5.3 啟動項目並測試自己在registerBeanDefinitions()方法中創建的bean PoolBean是否成功
@SpringBootApplication public class SpringBootApplication5 { public static void main(String[] args) { SpringApplication.run(SpringBootApplication5.class, args); } }
@RestController @RequestMapping("test") public class RestTestController { @Autowired private PoolBean poolBean; @GetMapping("registrar") public String registrarTest() { String jsonResult = ""; ObjectMapper mapper = new ObjectMapper(); try { jsonResult = mapper.writeValueAsString(poolBean); } catch (JsonProcessingException e) { e.printStackTrace(); } return jsonResult; } }
參考:
【1】Spring框架中@Import注解,https://segmentfault.com/a/1190000011068471
【2】@Import注解--導入資源,https://blog.csdn.net/u010502101/article/details/78760032
【3】一分鍾學會Spring注解之@Import注解,https://blog.51cto.com/4247649/2118354
【4】@Import、ImportSelector注解使用及源碼分析,https://juejin.im/post/5d63b455f265da03e52341d0
【5】深入理解Spring的ImportSelector接口,https://www.cnblogs.com/niechen/p/9262452.html
【6】ImportBeanDefinitionRegistrar, https://blog.csdn.net/baidu_19473529/article/details/90613661