Getting Started with Spring Boot - Advanced (7) - AutoConfigure

Auto-configuration is the biggest highlight of Spring Boot, which perfectly demonstrates CoC conventions due to configuration. Spring Boot can automatically configure various Spring sub-projects (Spring MVC, Spring Security, Spring Data, Spring Cloud, Spring Integration, Spring Batch, etc.) and various beans that need to be defined by third-party open source frameworks.

Spring Boot defines various XxxxAutoConfiguration configuration classes internally, and pre-defined various required beans. These configuration classes will only be used in certain situations.

(1) How to import the automatic configuration class
Look at the source code to see how the automatic configuration class is introduced.

a) Application entry
@SpringBootApplication
public class SpringBootDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootDemoApplication.class, args);
    }

}


b) 类注解 @SpringBootApplication = @EnableAutoConfiguration + @ComponentScan + @Configuration
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
		@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
    // ...
}

@Configuration
public @interface SpringBootConfiguration {
    // ...
}


c) Turn on the automatic configuration annotation @EnableAutoConfiguration
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    // ...
}


d) Import the configuration class EnableAutoConfigurationImportSelector extends AutoConfigurationImportSelector

In the AutoConfigurationImportSelector class, you can see
that spring-boot-autoconfigure-1.5.1.RELEASE.jar/META-INF/spring.factories is placed under SpringFactoriesLoader.loadFactoryNames().
quote
# 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.web.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration


How are these classes loaded after the application starts?
By executing the SpringApplication.run() method, the current SpringBootDemoApplication will be passed in as the source, and the SpringApplication class will also read the settings in spring.factories and build the Context of the application.

spring-boot-1.5.1.RELEASE.jar/META-INF/spring.factories
quote
# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer


spring-boot-autoconfigure-1.5.1.RELEASE.jar/META-INF/spring.factories
quote
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer


Correspondingly, when making war, the current SpringBootDemoApplication is also passed to ServletInitializer as source.
public class ServletInitializer extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(SpringBootDemoApplication.class);
    }
}


Configuration classes can also be imported by themselves
@Configuration
@Import({
        DispatcherServletAutoConfiguration.class,
        EmbeddedServletContainerAutoConfiguration.class,
        ErrorMvcAutoConfiguration.class,
        HttpEncodingAutoConfiguration.class,
        HttpMessageConvertersAutoConfiguration.class,
        JacksonAutoConfiguration.class,
        MultipartAutoConfiguration.class,
        ServerPropertiesAutoConfiguration.class,
        WebMvcAutoConfiguration.class
})
@ComponentScan
public class SpringBootDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootDemoApplication.class, args);
    }
}


(2) For an example of the internal composition of the automatic configuration class,

see org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration

@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurerAdapter.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
	public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
		return new OrderedHiddenHttpMethodFilter();
	}

	// ...

}


Conditional configuration Based on Spring's @Conditional, SpringBoot provides rich conditional configuration:
quote
@ConditionalOnClass : It takes effect when the class exists in the
classpath @ConditionalOnMissingClass : It takes effect when the class does not exist in the classpath @ConditionalOnBean : It takes effect
when the type of bean exists in the
DI container @ConditionalOnMissingBean : It takes effect when the type of bean does not exist in the DI container
@ConditionalOnSingleCandidate : It takes effect when there is only one bean of this type in the DI container or there is only one
@Primary @ConditionalOnExpression : When the result of the SpEL expression is true
@ConditionalOnProperty : It takes effect when the parameter settings or values ​​are the same
@ConditionalOnResource : It takes effect when the specified file exists Effective
@ConditionalOnJndi: Effective when the specified JNDI exists
@ConditionalOnJava: Effective when the specified Java version exists
@ConditionalOnWebApplication: Effective in a Web application environment
@ConditionalOnNotWebApplication: Effective in a non-Web application environment

@Conditional({OnClassCondition.class})
public @interface ConditionalOnClass {
    // ...
}

public class OnClassCondition extends SpringBootCondition implements ... {
    // ...
    // MatchType.PRESENT determines whether the specified class exists in the classpath
}

public abstract class SpringBootCondition implements Condition {
    // ...
}


execution order
quote
@AutoConfigureAfter: load after
the specified configuration class is initialized @AutoConfigureBefore: load @AutoConfigureOrder before the specified configuration class is initialized
: the smaller the number, the earlier the initialization


(3) Check the actual configuration of the project.
After the DEBUG mode is turned on, you can see the specific automatic configuration results in the console.

/src/main/resources/application.properties
quote
debug=true


quote
=========================
AUTO-CONFIGURATION REPORT
=========================


Positive matches:
-----------------

   DispatcherServletAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet'; @ConditionalOnMissingClass did not find unwanted class

(OnClassCondition)
      - @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)

   DispatcherServletAutoConfiguration.DispatcherServletConfiguration matched:
      - @ConditionalOnClass found required class 'javax.servlet.ServletRegistration'; @ConditionalOnMissingClass did not find unwanted class

(OnClassCondition)
      - Default DispatcherServlet did not find dispatcher servlet beans (DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition)

.......

Negative matches:
-----------------

   ActiveMQAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory'

(OnClassCondition)

   AopAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required classes 'org.aspectj.lang.annotation.Aspect', 'org.aspectj.lang.reflect.Advice' (OnClassCondition)

.......

Exclusions:
-----------

    None


Unconditional classes:
----------------------

    org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration

    org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration

    org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration

    org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration


For example, you can see that SpringBoot is enabled by default:
quote
DispatcherServletAutoConfiguration Register DispatcherServlet
EmbeddedServletContainerAutoConfiguration.EmbeddedTomcat Register Tomcat container
ErrorMvcAutoConfiguration Register exception handler
HttpEncodingAutoConfiguration Register encoding filter CharacterEncodingFilter
HttpMessageConvertersAutoConfiguration Register json or xml processor
JacksonAutoConfiguration Register json object parser
MultipartAutoConfiguration Register file transfer processor
TransactionAutoConfiguration Register transaction management processor
ValidationAutoConfiguration Register data validation The processor
WebMvcAutoConfiguration registers SpringMvc related processors




(4) Turn off the overall invalidation of automatic configuration

a) Use @Configuration @ComponentScan instead of @SpringBootApplication.

b) parameter settings
src/main/resources/application.properties
quote
spring.boot.enableautoconfiguration=false


partially nullified

@SpringBootApplication(exclude=HibernateJpaAutoConfiguration.class)


src/main/resources/application.properties
quote
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration


@SpringBootApplication(exclude={DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class})


src/main/resources/application.properties
quote
spring.autoconfigure.exclude[0]=org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
spring.autoconfigure.exclude[1]=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
spring.autoconfigure.exclude[2]=org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
spring.autoconfigure.exclude[3]=org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration


Reference:
http://qiita.com/kazuki43zoo/items/8645d9765edd11c6f1dd
http://d.hatena.ne.jp/Kazuhira/20170219/1487513127

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326612242&siteId=291194637