下面是我用spi实现的restTemplate对象的自动装载,与本文介绍的两种有所不同,感兴趣的可以看一下:
web-starter: web-starterhttps://gitee.com/qianwx/web-starter.git
Bean的动态装载有两种方式:
- ImportSelector
- ImportBeanDefinitionRegistrar
下面我们用两种方式来实现Bean的动态状态。
一、ImportSelector实现bean的动态装载
1.1 自定义类实现ImportSelector接口,重写selectImports接口,通知spring需要加载的配置类,完成bean的自动装载
/**
* bean的动态装载之importSelector - 自定义类=
* @author Qian
* @Since JDK1.8
* @Date 2021/11/23 23:44
*/
public class HelloImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
System.out.println("HelloImportSelector ============== selectImports");
return new String[] { HelloImportSelectorConfiguration.class.getName() };
}
}
/**
* 自定义配置类 --- 用于加载importselector包内的Demo7对象
* @author Qian
* @Since JDK1.8
* @Date 2021/11/23 23:47
*/
@ComponentScan("com.qwx.beanAutoload1.demo")
@Configuration
public class HelloImportSelectorConfiguration {
}
/**
* @author Qian
* @Since JDK1.8
* @Date 2021/11/23 23:46
*/
public class HelloService {
}
1.2 启动类上不加任何注解,HelloService未装载,获取对象时报错:
1.3 启动类上加注解@Import(HelloImportSelector.class):
成功获取到helloService对象。
1.4 ImportSelector实现bean的动态装载总结
- 写自定义的ImportSelector类,实现ImportSelector接口,重写selectImports方法;selectImports方法返回是HelloImportSelectorConfiguration的类名
- 写HelloImportSelectorConfiguration类,这是一个@Configuration注解的配置类,同时要扫描我们要装载类的包,或者在内部用bean方法的方式
- 在要装载类上加上@Component注解(如果是用配置类中bean方法的方式注入对象,则这个步骤不用)
- 在启动类上添加@Import注解
二、ImportBeanDefinitionRegistrar实现bean的动态装载
2.1 自定义类实现ImportBeanDefinitionRegistrar解口,重写registerBeanDefinitions方法,完成特定对象的装载
/**
* bean的动态装载之ImportBeanDefinitionRegistrar, 仿照@EnableFeignClients的写法
* @author Qian
* @Since JDK1.8
* @Date 2021/11/24 0:17
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(HelloImportBeanDefinitionRegistrar.class)
public @interface EnableHelloRegistrar {
}
/**
* @author Qian
* @Since JDK1.8
* @Date 2021/11/24 0:20
*/
public class HelloImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
BeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClassName(HelloService.class.getName());
registry.registerBeanDefinition("helloService", beanDefinition);
}
}
@Component
public class HelloService {
}
2.2 启动类上加注解
2.3 ImportBeanDefinitionRegistrar实现bean的动态装载总结
- 自定义@EnableHelloRegistrar 注解在@EnableHelloRegistrar注解上增加@Import(HelloImportBeanDefinitionRegistrar.class)注解
- HelloImportBeanDefinitionRegistrar类实现ImportBeanDefinitionRegistrar接口,重写registerBeanDefinitions方法,在此方法中设置GenericBeanDefinition对象的BeanClassName和registerBeanDefinition属性
- 在启动类上加@EnableHelloRegistrar 注解