1. 程式人生 > >4、Spring Boot 自動配置原理

4、Spring Boot 自動配置原理

add adp over 生成 修改 more servlet func details

1.4 Spring Boot 自動配置原理

簡介

spring boot自動配置功能可以根據不同情況來決定spring配置應該用哪個,不應該用哪個,舉個例子:

  • Spring的JdbcTemplate是不是在Classpath裏面?如果是,並且DataSource也存在,就自動配置一個JdbcTemplate的Bean
  • Thymeleaf是不是在Classpath裏面?如果是,則自動配置Thymeleaf的模板解析器、視圖解析器、模板引擎

那個這個是怎麽實現的呢?原因就在於它利用了Spring的條件化配置,條件化配置允許配置存在於應用中,但是在滿足某些特定條件前會忽略這些配置。

要實現條件化配置我們要用到@Conditional條件化註解。

本篇從如下幾個方面進行展開:

  1. @Conditional註解
  2. spring boot 的條件化配置詳解
  3. spring boot 自動配置源碼分析
  4. 自己動手實現spring boot starter pom

1.4.1 @Conditional 註解

@Conditional是由Spring 4提供的一個新特性,用於根據特定條件來控制Bean的創建行為。

1.4.2 Spring Boot 的條件化配置詳解

在spring boot項目中會存在一個名為spring-boot-autoconfigure的jar包,條件化配置就是在這個jar裏面實現的,它用到了如下的條件化註解,這些註解都是以@ConditionalOn開頭的,他們都是應用了@Conditional的組合註解:

  • @ConditionalOnBean ------------------------ 配置了某個特定的Bean
  • @ConditionalMissingBean ------------------- 沒有配置特定的Bean
  • @ConditionalOnCalss ----------------------- Classpath裏有指定的類
  • @ConditionalOnMissingCalss ---------------- Classpath缺少指定的類
  • @ConditionalOnExpression ------------------ 給定的Spring Expression Language(SpEL)表達式計算
  • @ConditionalOnJava ------------------------ Java的版本匹配特定值或者一個範圍值
  • @ConditionalOnProperty -------------------- 指定的配置屬性要有一個明確的值
  • @ConditionalOnResource -------------------- ClassPath裏有指定的資源
  • @ConditionalOnWebApplication -------------- 這是一個Web應用程序
  • @ConditionalOnNotWebApplication ----------- 這不是一個Web應用程序

以JdbcTemplateAutoConfiguration為例,它裏面有這段代碼:

@Bean
@Primary
@ConditionalOnMissingBean(JdbcOperations.class)
public JdbcTemplate jdbcTemplate() {
    return new JdbcTemplate(this.dataSource);
}

只有在不存在JdbcOperations(如果查看JdbcTemplate的源碼,你會發現JdbcTemplate類實現了JdbcOperations接口)實例的時候,才會初始化一個JdbcTemplate 的Bean。

1.4.3 Spring Boot 自動配置源碼分析

spring boot項目的啟動類用的註解--@SpringBootApplication是一個組合註解,其中@EnableAutoConfiguration是自動配置相關的。

查看@EnableAutoConfiguration註解源碼(本文基於spring-boot-starter-parent 2.1.0.RELEASE):

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};

}

而這個@EnableAutoConfiguration註解裏面有個@Import註解導入了EnableAutoConfigurationImportSelector用來實現具體的功能。

進入AutoConfigurationImportSelector.java裏面有個方法selectImports()調用了方法getAutoConfigurationEntry(),然後getAutoConfigurationEntry()方法又調用了getCandidateConfigurations(),進而調用了SpringFactoriesLoader.loadFactoryNames()方法

@Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
        AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
                .loadMetadata(this.beanClassLoader);
        AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
                autoConfigurationMetadata, annotationMetadata);
        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }

    /**
     * Return the {@link AutoConfigurationEntry} based on the {@link AnnotationMetadata}
     * of the importing {@link Configuration @Configuration} class.
     * @param autoConfigurationMetadata the auto-configuration metadata
     * @param annotationMetadata the annotation metadata of the configuration class
     * @return the auto-configurations that should be imported
     */
    protected AutoConfigurationEntry getAutoConfigurationEntry(
            AutoConfigurationMetadata autoConfigurationMetadata,
            AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        }
        AnnotationAttributes attributes = getAttributes(annotationMetadata);
        List<String> configurations = getCandidateConfigurations(annotationMetadata,
                attributes);
        configurations = removeDuplicates(configurations);
        Set<String> exclusions = getExclusions(annotationMetadata, attributes);
        checkExcludedClasses(configurations, exclusions);
        configurations.removeAll(exclusions);
        configurations = filter(configurations, autoConfigurationMetadata);
        fireAutoConfigurationImportEvents(configurations, exclusions);
        return new AutoConfigurationEntry(configurations, exclusions);
    }
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
            AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
                getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
        Assert.notEmpty(configurations,
                "No auto configuration classes found in META-INF/spring.factories. If you "
                        + "are using a custom packaging, make sure that file is correct.");
        return configurations;
    }

在SpringFactoriesLoader.loadFactoryNames()方法裏面,會調用loadSpringFactories(),然後查詢META-INF/spring.factories這個配置文件

    // 所要查詢的資源文件
    public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

    public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
        String factoryClassName = factoryClass.getName();
        return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
    }
    
    private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
        MultiValueMap<String, String> result = cache.get(classLoader);
        if (result != null) {
            return result;
        }

        try {
            Enumeration<URL> urls = (classLoader != null ?
                    classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
                    ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
            result = new LinkedMultiValueMap<>();
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                UrlResource resource = new UrlResource(url);
                Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                for (Map.Entry<?, ?> entry : properties.entrySet()) {
                    String factoryClassName = ((String) entry.getKey()).trim();
                    for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
                        result.add(factoryClassName, factoryName.trim());
                    }
                }
            }
            cache.put(classLoader, result);
            return result;
        }
        catch (IOException ex) {
            throw new IllegalArgumentException("Unable to load factories from location [" +
                    FACTORIES_RESOURCE_LOCATION + "]", ex);
        }
    }

SpringFactoriesLoader屬於Spring框架私有的一種擴展方案,其主要功能就是從指定的配置文件META-INF/spring.factories加載配置。

SpringFactoriesLoader.loadFactoryNames方法會掃描具有META-INF/spring.factories文件的jar包,而我們的spring-boot-autoconfigure.jar裏面就有一個這樣的文件,此文件中聲明了具體有哪些自動配置:

# Initializers
org.springframework.context.ApplicationContextInitializer=org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener

# Application Listeners
org.springframework.context.ApplicationListener=org.springframework.boot.autoconfigure.BackgroundPreinitializer

# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener

# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=org.springframework.boot.autoconfigure.condition.OnBeanCondition,org.springframework.boot.autoconfigure.condition.OnClassCondition,org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition

# 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.cloud.CloudServiceConnectorsAutoConfiguration,org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,org.springframework.boot.autoconfigure.elasticsearch.rest.RestClientAutoConfiguration,org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration,org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,org.springframework.boot.autoconfigure.security.servlet.SecurityRequestMatcherProviderAutoConfiguration,org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration

# Failure analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer,org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer

# Template availability providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider

我們上面提到的JdbcTemplateAutoConfiguration自動配置類就在裏面。

1.4.4 自己動手實現spring boot starter pom

接下來,我們就來寫一個簡單的spring boot starter pom。

  1. 新建starter maven項目 spring-boot-starter-autoconfigure
  2. 修改pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.hw</groupId>
    <artifactId>spring-boot-starter-autoconfigure</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>spring-boot-starter-autoconfigure</name>
    <description>Demo project for Spring Boot Autoconfigure</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!-- 這裏需要引入spring boot的自動配置作為依賴 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
  1. 屬性配置 HelloServiceProperties.java

package com.hw.springbootstarterautoconfigure.conifg;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * @Description TODO
 * @Author hw
 * @Date 2018/11/18 22:57
 * @Version 1.0
 */

/**
 * @ConfigurationProperties 自動匹配application.properties文件中hello.msg的值,然後賦值給類屬性msg,這裏的msg默認值為“spring boot”
 */
@ConfigurationProperties(prefix = "hello")
public class HelloServiceProperties {

    private static final String MSG = "spring boot";

    private String msg = MSG;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

}
  1. 判定依據類HelloService.java,後面的代碼會依據此類是否存在,來決定是否生產對應的Bean
package com.hw.springbootstarterautoconfigure.conifg;

/**
 * @Description TODO
 * @Author hw
 * @Date 2018/11/18 23:00
 * @Version 1.0
 */
public class HelloService {
    private String msg;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public String sayHello() {
        return "hello " + msg;
    }
}
  1. 自動配置類 HelloServiceAutoConfiguration.java,根據HelloServiceProperties提供的參數,並通過@ConditionalOnClass(HelloService.class)判定HelloService這個類在Classpath中是否存在,存在並且還沒有對應的Bean,就生成對應的helloService Bean
package com.hw.springbootstarterautoconfigure.conifg;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Description TODO
 * @Author hw
 * @Date 2018/11/18 23:01
 * @Version 1.0
 */
@Configuration
@EnableConfigurationProperties(HelloServiceProperties.class)
@ConditionalOnClass(HelloService.class)
@ConditionalOnProperty(prefix = "hello", matchIfMissing = true, value = "enabled")
public class HelloServiceAutoConfiguration {

    @Autowired
    HelloServiceProperties helloServiceProperties;

    @Bean
    @ConditionalOnMissingBean(HelloService.class)
    public HelloService helloService() {
        HelloService service = new HelloService();
        service.setMsg(helloServiceProperties.getMsg());
        return service;
    }
}
  1. 註冊配置,需要到META-INF/spring.factories文件中註冊改自動配置類:在src/main/source目錄下新建該文件,然後進行配置。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.hw.springbootstarterautoconfigure.conifg.HelloServiceAutoConfiguration
  1. 實現controller HelloController.java
package com.hw.springbootstarterautoconfigure.web;

import com.hw.springbootstarterautoconfigure.conifg.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Description TODO
 * @Author hw
 * @Date 2018/11/18 23:07
 * @Version 1.0
 */
@RestController
public class HelloController {

    /**
     * 代碼中沒有配置這個helloService Bean,但是自動配置能夠幫忙實例化,因此可以直接註入
     */
    @Autowired
    HelloService helloService;

    @RequestMapping(value = "/helloService")
    public String sayHello() {
        return helloService.sayHello();
    }
}
  1. 啟動項目 訪問/helloService 接口。 得到 hello spring boot
  2. 在application.properties裏面配置hello.msg=hw,然後再次訪問/helloService接口。得到 hello hw
  3. 本文完整代碼:Spring Boot自動配置

4、Spring Boot 自動配置原理