SpringBoot手写启动器
starter原理
-
spring在启动过程中会去扫描启动类上带有@Import注解,会将@Import导入的类注册到BeanFactoryRegistry中,Spring会帮我们去实例化类,放入IOC容器中。
/** * 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注解的值收集起来放入一个集合中,在之后的过程中帮我们实例化。
-
手写starter
-
创建一个maven项目,引入Spring-Context 依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.7</version> </dependency>
-
首先定义一个类:JalivvTemplate 主要用来实现功能的类
public class JalivvTemplate { public void say() { System.out.println("jalivv is so cool!"); } }
-
创建一个配置类,将 JalivvTemplate 注入的IOC容器中
public class JalivvAutoConfiguration { @Bean public JalivvTemplate jalivvTemplate() { return new JalivvTemplate(); } }
-
创建一个 MyImportSelector 实现 ImportSelector 接口
public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String[]{JalivvAutoConfiguration.class.getName()}; } }
-
定义一个注解 EnableJalivv,引入 MyImportSelector
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Import(MyImportSelector.class) public @interface EnableJalivv { }
测试
-
在我们项目中引入这个starter
<dependency> <groupId>com.jalivv.starter</groupId> <artifactId>jalivv-spring-boot-starter</artifactId> <version>1.0.0</version> </dependency>
-
在启动类上标上注解 EnableJalivv
@EnableJalivv @SpringBootApplication public class SpringbootProjectsApplication
-
我们可以从IOC容器中获取到 JalivvTemplate 对象,执行他的 say() 方法
ConfigurableApplicationContext run = SpringApplication.run(SpringbootProjectsApplication.class, args); JalivvTemplate jalivvTemplate = run.getBean("jalivvTemplate", JalivvTemplate.class); jalivvTemplate.say();
-
输出