Spring Boot自動配置原理、實戰

Spring Boot自動配置原理、實戰

Spring Boot自動配置原理

Spring Boot的自動配置註解是@EnableAutoConfiguration, 從上面的@Import的類可以找到下面自動加載自動配置的映射。

    org.springframework.core.io.support.SpringFactoriesLoader.loadFactoryNames(Class<?>, ClassLoader)
    public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {

        String factoryClassName = factoryClass.getName();

        try {

            Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :

                    lassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));

            List<String> result = new ArrayList<String>();

            while (urls.hasMoreElements()) {

                URL url = urls.nextElement();

                Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));

                String factoryClassNames = properties.getProperty(factoryClassName);

                result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));

            }

            return result;

        }

        catch (IOException ex) {

            throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +

                    "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);

        }

    }

這個方法會加載類路徑及所有jar包下META-INF/spring.factories配置中映射的自動配置的類。

    /**

     * The location to look for factories.

     * <p>Can be present in multiple JAR files.

     */

    public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

 

查看Spring Boot自帶的自動配置的包: spring-boot-autoconfigure-1.5.6.RELEASE.jar,打開其中的META-INF/spring.factories文件會找到自動配置的映射。

    # 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.CloudAutoConfiguration,\

    ...

再來看看數據源自動配置的實現註解

    @Configuration

    @ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })

    @EnableConfigurationProperties(DataSourceProperties.class)

    @Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })

    public class DataSourceAutoConfiguration {

    ...

@Configuration,@ConditionalOnClass就是自動配置的核心,首先它得是一個配置文件,其次根據類路徑下是否有這個類去自動配置。

自動配置實戰

所以,瞭解了自動配置的原理,來自己實現一個自動配置的玩意其實很簡單。

添加配置類:

    import org.slf4j.Logger;

    import org.springframework.context.EnvironmentAware;

    import org.springframework.core.env.Environment;

    import com.oceanpayment.common.utils.logger.LoggerUtils;

    public class EnvConfig implements EnvironmentAware {

        private final Logger logger = LoggerUtils.getLogger(this);

        private Environment env;

        public String getStringValue(String key) {

            return env.getProperty(key);

        }

        public Long getLongValue(String key) {

            String value = getStringValue(key);

            try {

                return Long.parseLong(value);

            } catch (Exception e) {

                logger.error("字符串轉換Long失敗:{} = {}", key, value);

            }

            return 0L;

        }

        public int getIntValue(String key) {

            return getLongValue(key).intValue();

        }

        @Override

        public void setEnvironment(Environment environment) {

            this.env = environment;

        }

    }

添加自動配置類:

    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;

    import org.springframework.context.annotation.Bean;

    import org.springframework.context.annotation.Configuration;

    import org.springframework.core.env.PropertyResolver;

    @Configuration

    @ConditionalOnClass(PropertyResolver.class)

    public class EnvAutoConfig {

        @Bean

        public EnvConfig envConfig() {

            return new EnvConfig();

        }

    }

創建META-INF/spring.factories文件,添加自動配置映射:

    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\\

    com.oceanpayment.common.config.env.EnvAutoConfig

這樣就搞定了。

查看自動配置報告

怎麼查看自己加的自動配置類有沒有被加載,或者查看所有自動配置激活的和未激活的可以通過以下幾種試查看。

  1. spring-boot:run運行的在對話框Enviroment中加入debug=true變量 

  2. java -jar xx.jar --debug

  3. main方法運行,在VM Argumanets加入-Ddebug

  4. 直接在application文件中加入debug=true

  5. 如果集成了spring-boot-starter-actuator監控,通過autoconfig端點也可以查看。

啓動後會在控制檯看到以下自動配置報告信息:

    =========================

    AUTO-CONFIGURATION REPORT

    =========================

    Positive matches:

    -----------------

       AopAutoConfiguration matched:

          - @ConditionalOnClass found required classes 'org.springframework.context.annotation.EnableAspectJAutoProxy', 'org.aspectj.lang.annotation.Aspect', 'org.aspectj.lang.reflect.Advice'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

          - @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)

       ...

       EnvAutoConfig matched:

          - @ConditionalOnClass found required class 'org.springframework.core.env.PropertyResolver'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

       ErrorMvcAutoConfiguration matched:

          - @ConditionalOnClass found required classes 'javax.servlet.Servlet', 'org.springframework.web.servlet.DispatcherServlet'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

          - @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)

       ErrorMvcAutoConfiguration#basicErrorController matched:

          - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.web.ErrorController; SearchStrategy: current) did not find any beans (OnBeanCondition)

       ...

    Negative matches:

    -----------------

       ActiveMQAutoConfiguration:

          Did not match:

             - @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition)

       AopAutoConfiguration.JdkDynamicAutoProxyConfiguration:

          Did not match:

             - @ConditionalOnProperty (spring.aop.proxy-target-class=false) found different value in property 'proxy-target-class' (OnPropertyCondition)

       ArtemisAutoConfiguration:

          Did not match:

             - @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory' (OnClassCondition)

       BatchAutoConfiguration:

          Did not match:

             - @ConditionalOnClass did not find required class 'org.springframework.batch.core.launch.JobLauncher' (OnClassCondition)

       ...

Positive matches:已經啓用的自動配置

Negative matches:未啓用的自動配置

從報告中看到自己添加的EnvAutoConfig已經自動配置了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章