上一篇文章主要聊聊如何实现一个带有拦截器功能的SPI。今天就来聊聊自定义的SPI如何与spring整合。
思考:我们实现的SPI要整合spring哪些东西?或者我们要利用spring的哪些特性实现我们哪些东西?
spring除了被大家熟知的IOC和AOP之外,还有它也提供了很丰富的扩展点,比如各种后置处理器,今天我们就聊聊大家相对熟悉的话题,如何通过自定义注解把SPI注入到spring容器中
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Activate {
String value() default "";
}
public class ActivateClassPathBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {
public ActivateClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
super(registry);
}
@SneakyThrows
@Override
protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
super.registerBeanDefinition(definitionHolder, registry);
Class clz = Class.forName(definitionHolder.getBeanDefinition().getBeanClassName());
Activate activate = AnnotationUtils.findAnnotation(clz,Activate.class);
if(ObjectUtils.isNotEmpty(activate) && StringUtils.isNotBlank(activate.value())){
String activateName = getEnvironment().resolvePlaceholders(activate.value());
registry.registerBeanDefinition(activateName,definitionHolder.getBeanDefinition());
}
}
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
return super.isCandidateComponent(beanDefinition) && beanDefinition.getMetadata()
.hasAnnotation(Activate.class.getName());
}
public class SpiRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware {
private Environment environment;
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
Set<String> basePackages = this.getBasePackages(importingClassMetadata);
String[] packages = {};
SpiBeanUtils.registerActivateInstances(registry,environment,basePackages.toArray(packages));
}
@Target(value = ElementType.TYPE)
@Retention(value = RetentionPolicy.RUNTIME)
@Documented
@Import(SpiRegister.class)
public @interface EnableSpi {
String[] value() default {};
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
}
1、在需要注入到spring容器的类上加上@Activate注解
@Activate("hello-mysql")
public class SpringMysqlDialect implements SpringSqlDialect {
@Autowired
private MysqlDialectService mysqlDialectService;
@Override
public String dialect() {
return mysqlDialectService.dialect();
}
}
2、启动类上加上扫描SPI范围注解
@SpringBootApplication(scanBasePackages = "com.github.lybgeek")
@EnableSpi(basePackages = "com.github.lybgeek")
public class SpiTestApplication implements ApplicationRunner
3、利用getBeansOfType进行验证
applicationContext.getBeansOfType(SpringSqlDialect.class)
.forEach((beanName,bean) -> System.out.println(beanName + "-->" + bean));
打印结果如下
hello-mysql-->com.github.lybgeek.dialect.mysql.SpringMysqlDialect@433348bc
说明已经注入到spring容器中
把项目的服务托管给spring ioc容器,可以算是与spring整合比较基础的动作,本文演示也是相对基础的一环,spring 强大的地方,在于它的扩展性,在spring bean的生命周期中,基本上随处可见扩展点,感兴趣的朋友后续可以自行体会验证
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有