@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