SpringBoot手写启动器

SpringBoot手写启动器

starter原理

  1. spring在启动过程中会去扫描启动类上带有@Import注解,会将@Import导入的类注册到BeanFactoryRegistry中,Spring会帮我们去实例化类,放入IOC容器中。

    image-20220121190650525

    /**
    	 * Recursively collect all declared {@code @Import} values. Unlike most
    	 * meta-annotations it is valid to have several {@code @Import}s declared with
    	 * different values; the usual process of returning values from the first
    	 * meta-annotation on a class is not sufficient.
    	 * <p>For example, it is common for a {@code @Configuration} class to declare direct
    	 * {@code @Import}s in addition to meta-imports originating from an {@code @Enable}
    	 * annotation.
    	 * @param sourceClass the class to search
    	 * @param imports the imports collected so far
    	 * @param visited used to track visited classes to prevent infinite recursion
    	 * @throws IOException if there is any problem reading metadata from the named class
    	 */
    private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)
      throws IOException {
    
      if (visited.add(sourceClass)) {
        for (SourceClass annotation : sourceClass.getAnnotations()) {
          String annName = annotation.getMetadata().getClassName();
          if (!annName.equals(Import.class.getName())) {
            collectImports(annotation, imports, visited);
          }
        }
        imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
      }
    }
    
    • getImports()方法会将@Imports注解的值收集起来放入一个集合中,在之后的过程中帮我们实例化。

      image-20220121192346413

手写starter

  1. 创建一个maven项目,引入Spring-Context 依赖

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.3.7</version>
    </dependency>
    
  2. 首先定义一个类:JalivvTemplate 主要用来实现功能的类

    public class JalivvTemplate {
      public void say() {
        System.out.println("jalivv is so cool!");
      }
    }
    
  3. 创建一个配置类,将 JalivvTemplate 注入的IOC容器中

    public class JalivvAutoConfiguration {
      @Bean
      public JalivvTemplate jalivvTemplate() {
        return new JalivvTemplate();
      }
    }
    
  4. 创建一个 MyImportSelector 实现 ImportSelector 接口

    public class MyImportSelector implements ImportSelector {
      @Override
      public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{JalivvAutoConfiguration.class.getName()};
      }
    }
    
  5. 定义一个注解 EnableJalivv,引入 MyImportSelector

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Documented
    @Import(MyImportSelector.class)
    public @interface EnableJalivv {
    }
    

测试

  1. 在我们项目中引入这个starter

    <dependency>
      <groupId>com.jalivv.starter</groupId>
      <artifactId>jalivv-spring-boot-starter</artifactId>
      <version>1.0.0</version>
    </dependency>
    
  2. 在启动类上标上注解 EnableJalivv

    @EnableJalivv
    @SpringBootApplication
    public class SpringbootProjectsApplication 
    
  3. 我们可以从IOC容器中获取到 JalivvTemplate 对象,执行他的 say() 方法

    ConfigurableApplicationContext run = SpringApplication.run(SpringbootProjectsApplication.class, args);
    JalivvTemplate jalivvTemplate = run.getBean("jalivvTemplate", JalivvTemplate.class);
    jalivvTemplate.say();
    
  4. 输出

    image-20220121201259852

posted @ 2022-01-21 20:15  jalivv  阅读(100)  评论(0编辑  收藏  举报