• 从-1开始实现一个中间件


    原创:艾小仙人

    别人都写从0开始实现xxx,我先从-1开始就显得更牛逼一些。

    今天,先开个头,来教大家怎么实现一个中间件。

    新建项目

    首先,我们新建一个多 module 的项目用于测试。

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

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    4. <modelVersion>4.0.0</modelVersion>
    5. <parent>
    6. <groupId>org.springframework.boot</groupId>
    7. <artifactId>spring-boot-starter-parent</artifactId>
    8. <version>2.7.0</version>
    9. <relativePath/> <!-- lookup parent from repository -->
    10. </parent>
    11. <groupId>com.aixiaoxian.infra</groupId>
    12. <artifactId>aixiaoxian-infra</artifactId>
    13. <version>0.0.1-SNAPSHOT</version>
    14. <name>aixiaoxian-infra</name>
    15. <description>aixiaoxian-infra</description>
    16. <packaging>pom</packaging>
    17. <properties>
    18. <java.version>1.8</java.version>
    19. </properties>
    20. <modules>
    21. <module>demo</module>
    22. <module>test-infra</module>
    23. </modules>
    24. <dependencies>
    25. </dependencies>
    26. <build>
    27. <plugins>
    28. <!-- Source -->
    29. <plugin>
    30. <artifactId>maven-source-plugin</artifactId>
    31. <inherited>true</inherited>
    32. <executions>
    33. <execution>
    34. <phase>package</phase>
    35. <goals>
    36. <goal>jar-no-fork</goal>
    37. </goals>
    38. </execution>
    39. </executions>
    40. </plugin>
    41. </plugins>
    42. </build>
    43. </project>

    开发中间件

    项目创建 OK 了,接着开始开发一个最最最简单的中间件。

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

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

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

    1. @Configuration
    2. public class TestConfiguration implements BeanDefinitionRegistryPostProcessor, EnvironmentAware {
    3. private Environment environment;
    4. @Bean
    5. public TestManager getTestManager() {
    6. return new TestManager();
    7. }
    8. @Override
    9. public void setEnvironment(Environment environment) {
    10. this.environment = environment;
    11. }
    12. }

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

    1. @Slf4j
    2. public class TestManager {
    3. public TestManager() {
    4. init();
    5. }
    6. public void init(){
    7. log.info("TestManager start");
    8. }
    9. }

    这样的话,一个最简单的中间件就开发好了,直接把他添加到demo模块中,启动测试即可。

    1. <dependency>
    2. <groupId>com.aixiaoxian.infra</groupId>
    3. <artifactId>test-infra</artifactId>
    4. <version>0.0.1-SNAPSHOT</version>
    5. </dependency>

    换个姿势

    我们换个姿势去创建 Bean,使用BeanDefinitionRegistryPostProcessor,让 TestConfiguration 去实现它,重写postProcessBeanDefinitionRegistry,注册一个新的 Bean aiManager,这样也是 OK的,写法很多,不再赘述。

    1. @Override
    2. public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
    3. BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(AiManager.class);
    4. beanDefinitionBuilder.addConstructorArgValue(this.environment);
    5. beanDefinitionRegistry.registerBeanDefinition("aiManager", beanDefinitionBuilder.getBeanDefinition());
    6. }
    1. @Slf4j
    2. public class AiManager {
    3. private Environment environment;
    4. public AiManager(Environment environment) {
    5. this.environment = environment;
    6. init();
    7. }
    8. public void init(){
    9. log.info("AiManager start");
    10. }
    11. }

    再换个姿势

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

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

    1. @Target({ElementType.TYPE})
    2. @Retention(RetentionPolicy.RUNTIME)
    3. @Import({TestImportSelector.class})
    4. @Documented
    5. public @interface TestAnnotation {
    6. }
    7. public class TestImportSelector implements DeferredImportSelector {
    8. @Override
    9. public String[] selectImports(AnnotationMetadata annotationMetadata) {
    10. return new String[]{AnnotationConfiguration.class.getName()};
    11. }
    12. }

    AnnotationConfiguration 写法也很简单了,这样也实现了自动装配,当然了你要是用上面的写法也能达到一样的效果,但是建议这样写,别问,问就是这样。

    1. public class AnnotationConfiguration implements BeanDefinitionRegistryPostProcessor {
    2. @Override
    3. public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
    4. BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(AnnotationManager.class);
    5. beanDefinitionRegistry.registerBeanDefinition("annotationManager", beanDefinitionBuilder.getBeanDefinition());
    6. }
    7. @Override
    8. public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
    9. }
    10. }
    11. @Slf4j
    12. public class AnnotationManager {
    13. public AnnotationManager() {
    14. init();
    15. }
    16. public void init(){
    17. log.info("AnnotationManager start");
    18. }
    19. }

    最后在demo启动类上打上我们这个注解。

    1. @SpringBootApplication
    2. @TestAnnotation
    3. public class DemoApplication {
    4. public static void main(String[] args) {
    5. SpringApplication.run(DemoApplication.class, args);
    6. }
    7. }

    最后我们可以看到输出:

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

    好了,就这样,我猜,没人需要这个源码吧?为了后面的文章,先写个这个铺垫一下,结束。

     

  • 相关阅读:
    Vue入门到放弃之旅今日开启第一篇
    Linux内存管理(二十 六):slub分配器之kmalloc详解
    《Java基础知识》Java 反射详解
    VisualStudio运行程序,点击应用程序时,弹出多个个窗体问题
    【电磁】基于 Biot-Savart 定律模拟沿螺旋(螺线管或环形)电流回路的磁场附matlab代码
    Windows10 Docker 安装教程
    百度网盘的音乐怎么分享到qq音乐里?
    3-2、python内置数据类型(列表和元组)
    编程小白如何成为大神
    react中使用threejs小试牛刀
  • 原文地址:https://blog.csdn.net/Moonxiyue/article/details/125408640