Spring Boot automatic configuration principle

Spring Boot’s autoconfiguration annotation is @enableAutoConfiguration, and the @import class above shows the following mapping for auto-loading and auto-configuration.

org.springframework.core.io.support.SpringFactoriesLoader.loadFactoryNames(Class<? >, ClassLoader)Copy the code
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); }}Copy the code

This method loads automatically configured classes mapped in meta-INF/Spring.Factories configurations in the classpath and all jars.

/**
 * 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";
Copy the code

The “spring-boot-autoconfigure-1.5.6.release. jar” file in the “Meta-INF/Spring. factories” file will find the auto-configured mappings.

# 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,\
...
Copy the code

Look again at the implementation annotations for the data source auto-configuration

@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })
public class DataSourceAutoConfiguration {
...
Copy the code

@configuration, @conditionalonClass is the heart of the auto-configuration. It must be a Configuration file, and then automatically configured according to whether the class is present in the classpath.

Automatic configuration combat

So, knowing the principle of automatic configuration, to implement an automatic configuration of the thing is actually very simple.

Add a configuration class:

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(" string failed to convert Long: {} = {}", key, value); } return 0L; } public int getIntValue(String key) { return getLongValue(key).intValue(); } @Override public void setEnvironment(Environment environment) { this.env = environment; }}Copy the code

Add an auto-configuration class:

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(); }}Copy the code

“/spring.factories”

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\\
com.oceanpayment.common.config.env.EnvAutoConfig
Copy the code

And we’re done.

View the automatic configuration report

How to check whether the auto-configuration class you added is loaded, or to see all auto-configuration active and inactive can be viewed through the following tests.

Java -jar xx.jar -debug \ 3, main =true; Add -ddebug \ to VM Argumanets. Add debug=true in application files. If spring-boot-starter-actuator monitoring is integrated, use the autoconfig endpoint to view it.

After startup, you will see the following automatic configuration report on the console:

========================= 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) .Copy the code

Positive matches: automatic configuration that is enabled \ Negative matches: automatic configuration that is not enabled

See from the report that the EnvAutoConfig I added has been automatically configured.

Recommended reading

Dry goods: Free 2TB architect four-stage video tutorial

Interview: the most complete Java multithreaded interview questions and answers

Tools: Recommended an online creation flow chart, mind mapping software

Share Java dry goods, high concurrency programming, hot technology tutorials, microservices and distributed technology, architecture design, blockchain technology, artificial intelligence, big data, Java interview questions, and cutting-edge hot news.