SpringBoot高级-自动配置之@Import注解
前言:通过前一篇的介绍,我们知道@Enable*底层依赖于@Import注解导入一些类,使用@Import导入的类会被Spring加载到IOC容器中,而@Import提供4种用法:
①、导入Bean;
②、导入配置类;
③、导入ImportSelector实现类。一般用于加载配置文件中的类;
④、导入ImportBeanDefinitionRegistrar实现类。
下面我们就这四种用法,一一举例。
一、利用@Import注解导入Bean,测试工程依旧为以前的功能,使用@Import注解,导入User类。
@SpringBootApplication
@Import(User.class)
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
Object user = context.getBean("user");
System.out.println(user);
}
}
启动程序测试结果:发现找不到user这个Bean,这是因为使用@Import注解,导入User类,给我们创建的bean的名称不是user,所以我们无法通过bean的名称(user)直接获取到bean。
方法一、我们可以通过User的全限定类名,从容器中获取到user这个Bean。
方法二(常用)、通过User类的类型从IOC容器中获取到bean,如下:
@SpringBootApplication
@Import(User.class)
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
//一、通过Bean的全限定类名获取Bean
Object user = context.getBean("com.winson.domain.User");
System.out.println(user);
//二、通过Bean的类型获取Bean
User user1 = context.getBean(User.class);
System.out.println(user1);
//getBeansOfType():获取bean的类型
Map<String, User> map = context.getBeansOfType(User.class);
System.out.println(map);
}
}
二、利用@Import注解导入配置类,使用@Import注解,导入UserConfig类。(注:之前讲解Enable*的案例就是利用@Import导入配置类,这里就不再做示例了)
三、利用@Import注解导入ImportSelector实现类
首先新建MyImportSelector类,实现ImportSelector类,重写接口selectImports()方法。之前提到了@Import的这种用法,一般用于加载配置文件中的类,通过selectImports()方法的importingClassMetadata对象,可以获取到注解中的信息,而再由于注解可以获取配置文件中的属性,以此在IOC容器中创建Bean,这里我们就不详细介绍了(注解是@ConditionalOnProperty可以获取配置文件属性)。这里我们再User实体类中又新建了以Role实体类,扩大测试范围。
/**
* @description:自定义的ImportSelector实现类
* @date: 2020/10/10 13:10
* @author: winson
*/
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.winson.domain.User", "com.winson.domain.Role"};
}
}
修改引导类,使用@Import注解导入自定义的ImportSelector实现类MyImportSelector
@SpringBootApplication
@Import(MyImportSelector.class)
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
User user1 = context.getBean(User.class);
System.out.println(user1);
Role role = context.getBean(Role.class);
System.out.println(role);
}
}
测试结果:
这里再补充一点关于ConfigurableApplicationContext对象的用法,这里我们都是用这个对象获取的bean,但是参数不同,上述是使用User类的类型作为参数,之前我们也用到过参数为user的,这是因为这个对象的getBean有两个重载方法,如下
四、利用@Import注解导入ImportBeanDefinitionRegistrar实现类
首先,新建一个自定义的ImportBeanDefinitionRegistrar接口实现类
/**
* @description:自定义ImportBeanDefinitionRegistrar的实现类MyImportBeanDefinitionRegistrar,重写接口的registerBeanDefinitions()方法,此方法有两个对象importingClassMetadata、registry,importingClassMetadata对象我们上面的示例已经解释过了,BeanDefinitionRegistry注册器,就是我们可以自定义将bean注册到IOC容器中,BeanDefinitionRegistry有一个registerBeanDefinition()方法,第一个参数:自定义Bean的名称,第二个参数:Bean的定义(Bean的信息),通过BeanDefinitionBuilder对象将User类的Bean信息获取,然后作为参数,就可以自定义Bean到IOC容器中了。
* @date: 2020/10/10 13:40
* @author: winson
*/
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//手动注入User的Bean示例
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
registry.registerBeanDefinition("user", beanDefinition);
}
}
修改引导类
@SpringBootApplication
@Import(MyImportBeanDefinitionRegistrar.class)
public class SpringbootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringbootEnableApplication.class, args);
//由于我们自定义了Bean的名称,所以这里我们就可以通过Bean的名称来获取Bean。
Object user = context.getBean("user");
System.out.println(user);
}
}
启动程序,测试结果