今天是:
带着程序的旅程,每一行代码都是你前进的一步,每个错误都是你成长的机会,最终,你将抵达你的目的地。
title

spring boot 自动配置原理

springboot在可能让我们的配置减到最少,尝试猜测和配置您能需要的bean。根据类路径和定义的bean来应用自动配置类。在我们工程中需要添加功能而引入某些jar包时,比如我们需要配置缓存,数据库,定时任务。这通常需要我们额外的配置,spring boot 通过自动配置这一机制将需要的bean注入到spring的IOC容器中, 这减少了我们的配置。而我们在开发过程中也可以随时覆盖这些自动配置的bean。也可以通过spring.autoconfigure.exclude,注解exclude排除指定的自动配置bean。

spring boot 注册自动配置类通过\META-INF\spring.factories,注册时会根据@ConditionalOnxxx 注解的条件判断是否注册到spring 容器。

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\

下面拿一个jackson的自动配置类来说

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(ObjectMapper.class)
public class JacksonAutoConfiguration {

	private static final Map<?, Boolean> FEATURE_DEFAULTS;

	static {
		Map<Object, Boolean> featureDefaults = new HashMap<>();
		featureDefaults.put(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
		featureDefaults.put(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS, false);
		FEATURE_DEFAULTS = Collections.unmodifiableMap(featureDefaults);
	}

	@Bean
	public JsonComponentModule jsonComponentModule() {
		return new JsonComponentModule();
	}

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(Jackson2ObjectMapperBuilder.class)
	static class JacksonObjectMapperConfiguration {

		@Bean
		@Primary
		@ConditionalOnMissingBean
		ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
			return builder.createXmlMapper(false).build();
		}

	}

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(ParameterNamesModule.class)
	static class ParameterNamesModuleConfiguration {

		@Bean
		@ConditionalOnMissingBean
		ParameterNamesModule parameterNamesModule() {
			return new ParameterNamesModule(JsonCreator.Mode.DEFAULT);
		}

	}

在上面的示例中,如果ApplicationContext中不包含ObjectMapper类型的bean,它将创建ObjectMapper bean。另一个注释@ConditionalOnBean与@ConditionalOnMissingBean注释相反。该条件只能匹配到目前为止应用程序上下文已处理的bean。

设置自定义自动配置

定义自动配置类

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(DataSource.class)
public class MyAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public MyService myService() {
        return new MyService(true);
    }
}
...
---------------------------------------
@Data
public class MyService {
    boolean autoConfig;
    public MyService(boolean autoConfig) {
        this.autoConfig=autoConfig;
    }
}

在resources\META-INF下创建spring.factories 文件

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.springboot.config.MyAutoConfiguration

创建测试类,测试成功证明MyService成功注册在容器当中。

public class AutoConfigurationTest {

    private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
            .withConfiguration(AutoConfigurations.of(MyAutoConfiguration.class));

    @Test
    public  void serviceNameCanBeConfigured() {
        this.contextRunner.withUserConfiguration(MyAutoConfiguration.class).run((context) -> {
            assertThat(context).hasSingleBean(MyService.class);
            assertThat(context.getBean(MyService.class).isAutoConfig()).isTrue();
        });
    }
}

如果我们将日志配置为logging.level.org.springframework=DEBUG或者使用了spring-boot-starter-actuator ,在启动spring应用时将看到自动配置的类,如下:

分享到:

专栏

类型标签

网站访问总量