1

Preface

The previous article mainly about how to implement an SPI with interceptor function at 1618a157ae8884. Let’s talk about how the custom SPI integrates with spring today.

Thinking: What do we need to integrate spring into the SPI we implement? Or what features of spring should we use to achieve what we have?

In addition to the well-known IOC and AOP, spring also provides a wealth of extension points, such as various post processors. Today we will talk about topics that are relatively familiar to everyone, how to use custom annotations to convert SPI Inject into the spring container

Integrated thinking

1. Custom annotations

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Activate {

    String value() default "";
}

2. Custom bean definition scanner

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());
    }

3. Define ImportBeanDefinitionRegistrar

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));
    }

4. Custom enabled annotation

@Target(value = ElementType.TYPE)
@Retention(value = RetentionPolicy.RUNTIME)
@Documented
@Import(SpiRegister.class)
public @interface EnableSpi {

  
    String[] value() default {};

 
    String[] basePackages() default {};

  
    Class<?>[] basePackageClasses() default {};
}

Sample demo

1. Add @Activate annotation to the class that needs to be injected into the spring container
@Activate("hello-mysql")
public class SpringMysqlDialect implements SpringSqlDialect {

    @Autowired
    private MysqlDialectService mysqlDialectService;

    @Override
    public String dialect() {
        return mysqlDialectService.dialect();
    }


}
2. Add the scan SPI range annotation to the startup class
@SpringBootApplication(scanBasePackages = "com.github.lybgeek")
@EnableSpi(basePackages = "com.github.lybgeek")
public class SpiTestApplication implements ApplicationRunner 
3. Use getBeansOfType to verify
 applicationContext.getBeansOfType(SpringSqlDialect.class)
                .forEach((beanName,bean) -> System.out.println(beanName + "-->" + bean));

The print result is as follows

hello-mysql-->com.github.lybgeek.dialect.mysql.SpringMysqlDialect@433348bc

Description has been injected into the spring container

Summarize

Hosting the project's services to the spring ioc container can be regarded as a relatively basic action to integrate with spring. This article demonstrates also a relatively basic link. The strength of spring lies in its scalability. In the life cycle of spring beans, basically Extension points can be seen everywhere, interested friends can experience the verification by themselves

demo link

https://github.com/lyb-geek/springboot-learning/tree/master/springboot-spi-enhance/springboot-spi-framework-spring


linyb极客之路
344 声望193 粉丝