SpringBoot Auto-Configuration

225 阅读3分钟

简介

SpringBoot为我们提供了是非便利的自动装配功能,让我们能轻松的在团队合作中发布自己或者小团队的组件,其他团队能很便捷的引用,下面我们来看看工作中常用的一些处理自动配置的技巧。

自动配置

我们只需要在项目resources/META-INF/spring.factories文件中增加org.springframework.boot.autoconfigure.EnableAutoConfiguration节点,并配置需要自动配置的类,SpringBoot就可以为我们完成该类的加载,如果有多个类需要自动配置用逗号隔开。

举例:

//  resources/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.demo.DemoAutoConfigure

具体原理《SpringBoot自动配置及自定义Starter》

使用

规范

自动配置的类不能被扫描,同时也不能在自动配置的类中扫描其他类,如果需要引入其他类可以使用@Import注解,举例:


@Import({
    DemoService.class
})
public class DemoAutoConfigure {

}

这是一个最简单的自动配置类,我们也不需要在类上添加@Configuration注解,SpringBoot会自动将该类加载成Bean,该自动配置只做了一件事就是将DemoService加载到ApplicationContext中,我们在后续使用中只需要直接注入到使用的地方即可。

public Class TestService{
    @Autowird
    private DemoService demoService;
}

顺序控制

@AutoConfigureAfter@AutoConfigureBefore,如果需要控制自动配置的加载顺序,我们可以使用这两个注解,顾名思义这两个注解是控制后加载和前加载的,举例:


@AutoConfigureBefore({DataJdbcRuntimeAutoConfigure.class})
@AutoConfigureAfter({DataSourceAutoConfiguration.class})
public class DemoAutoConfigure {
    
    @Bean
    public DemoService demoService(DataSource dataSource){
        return new DemoService(dataSource);
    }
}

这个例子中我们删除了@Import注解,采用@Bean注解将DemoService声明为一个bean对象并加载到spring容器中,我们通过构造函数new了一个DemoService对象,该对象需要一个DataSource作为参数,我们可以方法参数的形式直接将DataSource参数注入到demoService()方法中并传递给new DemoService(dataSource)所以我们需要保证在DemoAutoConfigure加载时DataSource对象已经加载到了spring容器中,这时就可以采用@AutoConfigureAfter({DataSourceAutoConfiguration.class})来保证自动配置的加载顺序。

条件控制

@ConditionalOnClass和@ConditionalOnMissingClass

这两个注解控制自动配置类需要在有某个类或者没有某个类时才加载,比如:


@ConditionalOnClass(DemoService.class)
public class DemoAutoConfigure {
    
    @Bean
    public DemoService demoService(){
        return new DemoService();
    }
}

DemoAutoConfigure只有在DemoService存在的时候才会加载,这在我们增强一些组件时是很有用的,只有存在时才增强。

@ConditionalOnBean和@ConditionalOnMissingBean

这两个注解控制自动配置类需要在ApplicationContext存在这个类型的bean对象才会加载,比如:


public class DemoAutoConfigure {
    
    @Bean
    @ConditionalOnMissingBean
    public DemoService demoService(){
        return new DemoService();
    }
}

我们在demoService()方法上标记了@Bean@ConditionalOnMissingBean两个注解,这样在ApplicationContext中不存在DemoService类型的bean对象时则会new一个DemoService并加载到ApplicationContext中;利用这个特性我们可以给自己的组件定义默认的行为,同时组件使用者可以定义自己的DemoService并加载到ApplicationContext中以此来覆盖组件的默认行为。

@ConditionalOnProperty

@ConditionalOnProperty(value = "enabled", prefix = "demo", havingValue = "true", matchIfMissing = false)
public class DemoAutoConfigure {
    
    @Bean
    @ConditionalOnMissingBean
    public DemoService demoService(){
        return new DemoService();
    }
}

该注解可以让我们用配置文件或者启动参数控制自动配置类是否加载,上面的例子表示,在配置参数中存在demo.enabled=trueDemoAutoConfigure才会加载,注意这个的配置参数不仅仅是配置文件中的参数,还包括环境变量、jvm参数、SpringApplicationJson参数等。我们平常用的框架经常会采用这种方式控制,比如:

spring:
  application:
    name: demo
  cloud:
    nacos:
      discovery:
        enabled: false  //关闭nacos注册

测试

测试自动配置我们需要用到ApplicationContextRunner

class DemoAutoConfigureTest {

    private final ApplicationContextRunner contextRunner = new ApplicationContextRunner();

    @Test
    void demoServiceTest() {
        this.contextRunner
        .withPropertyValues("demo.enabled=true")   //指定参数
        .withConfiguration(AutoConfigurations.of(DemoAutoConfigure.class)) //指定配置类
        .run((context) -> {
            assertThat(context).hasSingleBean(DemoService.class);
            assertThat(context).getBean("demoService").isSameAs(context.getBean(DemoService.class));
        });
    }

}

上面的例子中我们用withPropertyValues指定了参数,withConfiguration指定了配置类,AssertJ进行了类型判断

自定义Starter

利用springboot自动配置定义自己的Starter可以参考《SpringBoot自动配置及自定义Starter》

至此本教程就结束了,希望大家收获满满

有问题欢迎留言