自定义SpringBoot的自动配置
一.前言
SpringBoot通过自动配置实现了开箱即用的功能,极大方便了项目的开发,参照它的思路,我们是否也可以实现一个自定义的自动配置呢。
二.实现思路
1.自定义两个自动配置类
@Configurationstatic class AutoConfiguration1{@Beanpublic Bean1 Bean1(){return new Bean1();}}
@Configurationstatic class AutoConfiguration2{@Beanpublic Bean2 Bean2(){return new Bean2();}}
2.spring.factories文件配置
其中有一个键为org.springframework.boot.autoconfigure.EnableAutoConfiguration,SpringBoot中通过这个键值来配置自定义的类
com.example.springdemo.demos.a04.TestAutoConfiguration$MyImportSelector=\
com.example.springdemo.demos.a04.TestAutoConfiguration.AutoConfiguration1,\
com.example.springdemo.demos.a04.TestAutoConfiguration.AutoConfiguration2org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.springdemo.demos.a07.TestMyBoot.AutoConfiguration1,\
com.example.springdemo.demos.a07.TestMyBoot.AutoConfiguration2
3.在自定义的自动配置类上加@Import(AutoConfigurationImportSelector.class)
SpringBoot是通过这个导入类导入自动配置文件的
@Configuration@Import(AutoConfigurationImportSelector.class)static class Config{}
进入AutoConfigurationImportSelector类,粗略看下实现原理
可以看到getAutoConfigurationEntry方法,获取配置。
点开getCandidateConfigurations方法可以看到具体实现
里面也是通过SpringFactoriesLoader.loadFactoryNames()加载配置文件。
打开this.getSpringFactoriesLoaderFactoryClass()可以看到它的加载的类EnableAutoConfiguration
者也是为什么要在配置类文件里面把自定义的配置类的键值配置为EnableAutoConfiguration的原因,只有这样在配合AutoConfigurationImportSelector便可以使用SpringBoot的自动配置配置我们的自定义类。
4.实战
package com.example.springdemo.demos.a07;import org.springframework.boot.autoconfigure.AutoConfigurationImportSelector;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DeferredImportSelector;
import org.springframework.context.annotation.Import;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.core.type.AnnotationMetadata;/*** @author zhou* @version 1.0* @description TODO* @date 2025/8/24 16:11*/
public class TestMyBoot {public static void main(String[] args) {AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext();context.registerBean("config", Config.class);context.refresh();for(String name : context.getBeanDefinitionNames()){String resource = context.getBeanDefinition(name).getResourceDescription();if(resource != null){System.out.println(name + "来源:"+resource);}}context.close();}@Configuration@Import(AutoConfigurationImportSelector.class)static class Config{}/*static class MyImportSelector implements DeferredImportSelector{@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {return SpringFactoriesLoader.loadFactoryNames(MyImportSelector.class,null).toArray(new String[0]);}}*/@Configurationstatic class AutoConfiguration1{@Beanpublic Bean1 Bean1(){return new Bean1();}}@Configurationstatic class AutoConfiguration2{@Beanpublic Bean2 Bean2(){return new Bean2();}}static class Bean1{}static class Bean2{}}
测试结果:
里面已经报错了,SpringBoot自动配置注解会做一个判断,不能通过直接使用@Import(AutoConfigurationImportSelector.class)的方式使用自动注入。
我们需要使用@EnableAutoConfiguration替代即可
已经正确导入我们自动配置的类了。