别人都写从0开始实现自动装配,我先从-1开始

别人写从0开始实现xxx,我从-1开始更牛逼。

今天,我们先来教大家如何实现一个中间件。

新项目

首先,我们创建一个用于测试的多模块项目。

项目包含两个模块,test-infra用户中间件模块开发,demo进行测试。



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.7.0
         
    
    com.aixiaoxian.infra
    aixiaoxian-infra
    0.0.1-SNAPSHOT
    aixiaoxian-infra
    aixiaoxian-infra
    pom
    
        1.8
    
    
        demo
        test-infra
    
    
    
    
        
            
            
                maven-source-plugin
                true
                
                    
                        package
                        
                            jar-no-fork
                        
                    
                
            
        
    

开发中间件

项目创建OK,接下来开始开发最简单的中间件。

在resources目录下创建一个META-INFA/spring.factories文件用于自动组装,不要问我什么是自动组装,然后配置一个自动组装类。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=
com.aixiaoxian.testInfra.config.TestConfiguration

实现TestConfiguration最简单的方法是使用@Bean注解声明一个bean,交给Spring管理。

@Configuration
public class TestConfiguration implements BeanDefinitionRegistryPostProcessor, EnvironmentAware {
    private Environment environment;
    @Bean
    public TestManager getTestManager() {
        return new TestManager();
    }
  
   @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
}

然后实现TestManager,真正的中间件逻辑的处理部分。

@Slf4j
public class TestManager {
    public TestManager() {
        init();
    }
    public void init(){
        log.info("TestManager start");
    }
}

本例中最简单的中间件就开发完成了,添加到demo模块开始测试即可。

 
   com.aixiaoxian.infra
   test-infra
   0.0.1-SNAPSHOT
 

改变位置

我们换个姿势创建Bean,使用BeanDefinitionRegistryPostProcessor,让TestConfiguration实现,重写postProcessBeanDefinitionRegistry,注册一个新的Bean aiManager。

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
    BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(AiManager.class);
    beanDefinitionBuilder.addConstructorArgValue(this.environment);
    beanDefinitionRegistry.registerBeanDefinition("aiManager", beanDefinitionBuilder.getBeanDefinition());
}

@Slf4j
public class AiManager {
    private Environment environment;
    public AiManager(Environment environment) {
        this.environment = environment;
        init();
    }
    public void init(){
        log.info("AiManager start");
    }
}

另一个职位

对自动装配创建Bean有基本的了解,如果我想声明一个注解给别人使用怎么办?

首先创建一个注解,注意我使用了@Import注解,TestImportSelector实现了TestImportSelector接口。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import({TestImportSelector.class})
@Documented
public @interface TestAnnotation {
}
public class TestImportSelector implements DeferredImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{AnnotationConfiguration.class.getName()};
    }
}

AnnotationConfiguration 的写法也很简单,也实现了自动组装。当然用上面的写法也可以达到同样的效果,但是建议这样写,不问,问就行。

public class AnnotationConfiguration implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(AnnotationManager.class);
        beanDefinitionRegistry.registerBeanDefinition("annotationManager", beanDefinitionBuilder.getBeanDefinition());
    }
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
    }
}
@Slf4j
public class AnnotationManager {
    public AnnotationManager() {
        init();
    }
    public void init(){
        log.info("AnnotationManager start");
    }
}

最后,将我们的注解放在演示启动类上。

@SpringBootApplication
@TestAnnotation
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

终于可以看到输出了:

2022-06-21 19:05:07.433  INFO 4598 --- [           main] c.a.testInfra.manager.TestManager        : TestManager start
2022-06-21 19:05:07.456  INFO 4598 --- [           main] c.a.testInfra.manager.AiManager          : AiManager start
2022-06-21 19:05:07.456  INFO 4598 --- [           main] c.a.testInfra.manager.AnnotationManager  : AnnotationManager start

好的,就是这样,我猜没有人需要这个源代码吧?为了后面的文章,我会写这个铺垫和结束。

© 版权声明
THE END
喜欢就支持一下吧
点赞121 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片