钱艷芳 发表于 昨天 12:28

SpringBoot3 自定义 Starter

SpringBoot3 自定义 Starter

SpringBoo3 最简单自定义 Starter 步骤。
1. 启动一个空白模板项目

gradle或者maven项目
引入如下依赖:
implementation("org.springframework.boot:spring-boot-autoconfigure:3.5.0")2. 手写自动配置类

package edu.tyut.config

import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.BeanFactory
import org.springframework.boot.autoconfigure.AutoConfiguration
import org.springframework.boot.autoconfigure.AutoConfigurationPackages
import org.springframework.context.annotation.Bean

private const val BASE_PACKAGE: String = "basePackage"

/**
* custom config
*/
@AutoConfiguration
internal open class CustomAutoConfig {
    private val logger: Logger = LoggerFactory.getLogger(this.javaClass)
    @Bean(value = )
    internal open fun getBasePackage (
      beanFactory: BeanFactory
    ): String {
      val packages: List<String> = AutoConfigurationPackages.get(beanFactory)
      logger.info("CustomAutoConfig AutoConfiguration Packages: $packages")
      return packages.firstOrNull() ?: "edu.tyut"
    }
}3. 注册自动配置类

在文件resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports下注册:
edu.tyut.config.CustomAutoConfigEnd, 怎么样是不是非常简单
原理解析

1. 启动类的注解@SpringBootApplication

源码如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
                @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
...
}2. @EnableAutoConfiguration

源码如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
...
}3. AutoConfigurationImportSelector

源码如下:
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
                ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
        private final Class<?> autoConfigurationAnnotation;
        AutoConfigurationImportSelector(Class<?> autoConfigurationAnnotation) {
                this.autoConfigurationAnnotation = (autoConfigurationAnnotation != null) ? autoConfigurationAnnotation
                                : AutoConfiguration.class;
        }
...
        protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
                ImportCandidates importCandidates = ImportCandidates.load(this.autoConfigurationAnnotation,
                                getBeanClassLoader());
                List<String> configurations = importCandidates.getCandidates();
                Assert.state(!CollectionUtils.isEmpty(configurations),
                                "No auto configuration classes found in " + "META-INF/spring/"
                                                + this.autoConfigurationAnnotation.getName() + ".imports. If you "
                                                + "are using a custom packaging, make sure that file is correct.");
                return configurations;
        }
...
}代码解读
查看该类构造函数可以发现其有一个成员变量autoConfigurationAnnotation,其值为org.springframework.boot.autoconfigure.AutoConfiguration.
getCandidateConfigurations的参数为即为org.springframework.boot.autoconfigure.AutoConfiguration.
4. org.springframework.boot.context.annotation.ImportCandidates

源码如下:
public final class ImportCandidates implements Iterable<String> {
...
        public static ImportCandidates load(Class<?> annotation, ClassLoader classLoader) {
                Assert.notNull(annotation, "'annotation' must not be null");
                ClassLoader classLoaderToUse = decideClassloader(classLoader);
                String location = String.format(LOCATION, annotation.getName());
                Enumeration<URL> urls = findUrlsInClasspath(classLoaderToUse, location);
                List<String> importCandidates = new ArrayList<>();
                while (urls.hasMoreElements()) {
                        URL url = urls.nextElement();
                        importCandidates.addAll(readCandidateConfigurations(url));
                }
                return new ImportCandidates(importCandidates);
        }
}代码解读:
找到类路径下所有的META-INF/spring/full-qualified-annotation-name.imports文件,读取内容(自动配置类的全限定名), 如果在自动配置类没有org.springframework.boot.autoconfigure.AutoConfiguration注解,会抛出IllegalArgumentException异常。
META-INF/spring/full-qualified-annotation-name.imports文件 -> URL -> BufferedReader -> ImportCandidates.
5. ImportCandidates

ImportCandidates包含了所有的自动配置类,SpringBoot会对其进行进一步的处理。
End 本文分享结束, 有什么不足还请大家指出

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: SpringBoot3 自定义 Starter