Spring Boot Auto-configuration

Keywords: Programming Spring Apache Attribute Java

In this chapter, we will reveal the Spring Boot Auto Configuration mechanism for you. When we talk about auto-configuration, we can't do without the @Enable AutoConfiguration annotation.

package org.springframework.boot.autoconfigure;

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

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

Two meta-annotations are involved here: @AutoConfiguration Package, @Import (Enable AutoConfiguration Import Selector.class), where @AutoConfiguration Package is defined as follows:

package org.springframework.boot.autoconfigure;

import ....

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

}

@ The @Import meta-annotation is used in the AutoConfiguration Package annotation definition. The value of the annotation attribute is AutoConfiguration Packages. Registrar. class, and the AutoConfiguration Packages. Registrar class implements the interface ImportBean Definition Registrar.

@ Import annotations can accept Java classes of the following defined types

  • Classes annotated with @Configuration
  • ImportSelector implementation class: Processing the @Configuration annotation class in code
  • DeferredImportSelector implementation class: Similar to ImportSelector, the difference is that processing operations are delayed until all other configuration items are processed.
  • ImportBeanDefinitionRegistrar Implementation Class

AutoConfiguration Packages. Registrar registers beans with the Spring container, which itself stores a list of user-defined configuration packages. Spring Boot itself uses this list. For example, for spring-boot-autoconfigure data access configuration classes, you can get this configuration list through the static method: ** AutoConfiguration Packages. get (Bean Factory)**. Here is the sample code.

package com.logicbig.example;

import ...

@EnableAutoConfiguration
public class AutoConfigurationPackagesTest {

   public static void main (String[] args) {

       SpringApplication app =
                     new SpringApplication(AutoConfigurationPackagesTest.class);
       app.setBannerMode(Banner.Mode.OFF);
       app.setLogStartupInfo(false);
       ConfigurableApplicationContext c = app.run(args);
       List<String> packages = AutoConfigurationPackages.get(c);
       System.out.println("packages: "+packages);
   }
}

The code output is as follows:

2017-01-03 10:17:37.372  INFO 10752 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@67b467e9: startup date [Tue Jan 03 10:17:37 CST 2017]; root of context hierarchy
2017-01-03 10:17:38.155  INFO 10752 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
packages: [com.logicbig.example]
2017-01-03 10:17:38.170  INFO 10752 --- [       Thread-1] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@67b467e9: startup date [Tue Jan 03 10:17:37 CST 2017]; root of context hierarchy
2017-01-03 10:17:38.171  INFO 10752 --- [       Thread-1] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown

The **@Import (Enable AutoConfiguration Import Selector. class) annotation is the startup entry for the auto-configuration mechanism. Enable AutoConfiguration Import Selector implements the interface Deferred Import Selector, which calls the SpringFactories Loader. loadFactoryNames ()** method internally, which loads the configuration class from META-INF/spring.factories.

	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;
	}

Find the value of the key value org.spring framework.boot.autoconfigure.EnableAutoConfiguration from spring.factories:

spring-boot-autoconfigure is implicitly included in all startups by default

One of the following sections of the configuration class JmxAutoConfiguration

 package org.springframework.boot.autoconfigure.jmx;

   .......
 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.autoconfigure.condition.SearchStrategy;
  .....

 @Configuration
 @ConditionalOnClass({ MBeanExporter.class })
 @ConditionalOnProperty(prefix = "spring.jmx", name = "enabled", havingValue = "true", matchIfMissing = true)
 public class JmxAutoConfiguration implements
                                    EnvironmentAware, BeanFactoryAware {
    .....
 }

@ConditionalOnClass

@ Conditional OnClass is defined by the meta annotation **@Conditional(OnClassCondition.class **), and we know that,@ Conditional is a conditional annotation, and only if the condition is true will the classes and methods of @Conditional annotation be loaded into the Spring component container. For the above example code snippet, only when MBeanExporter.class is already included in the classpath (specific checking is similar to the loading logic of Class.forName, when the target class is included in the classpath, the method returns true, otherwise false), OnClassCondition # matches() will return to true.

@ConditionalOnProperty

Similar to **@ConditionalOnClass, @ConditionalOnProperty is another @Conditional type variable defined by the meta-annotation @Conditional(OnPropertyCondition.class)**. Only when the target attribute contains the specified value will ** OnPropertyCondition#matches()** return true, or is it the code segment above:

  @ConditionalOnProperty(prefix = "spring.jmx", name = "enabled",
                         havingValue = "true", matchIfMissing = true)

If our application is configured with spring.jmx.enabled=true, the Spring container will automatically register Jmx AutoConfiguration, and matchIfMissing=true means true by default (configuration properties are not set).

Other Conditional Notes

Package'org. spring framework. boot. autoconfigure. condition', all condition annotations follow the Conditional OnXyz `naming convention. If you want to develop custom startup packages, you need to understand these API s, and for other developers, it's best to understand the basic operating mechanism as well.

Use the debug parameter

@EnableAutoConfiguration
public class DebugModeExample {

  public static void main (String[] args) {
      //just doing this programmatically for demo
      String[] appArgs = {"--debug"};

      SpringApplication app = new SpringApplication(DebugModeExample.class);
      app.setBannerMode(Banner.Mode.OFF);
      app.setLogStartupInfo(false);
      app.run(appArgs);
    }
}

output

2017-01-02 21:15:17.322 DEBUG 5704 --- [           main] o.s.boot.SpringApplication               : Loading source class com.logicbig.example.DebugModeExample
2017-01-02 21:15:17.379 DEBUG 5704 --- [           main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped (empty) config file 'file:/D:/LogicBig/example-projects/spring-boot/boot-customizing-autoconfig/target/classes/application.properties' (classpath:/application.properties)
2017-01-02 21:15:17.379 DEBUG 5704 --- [           main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped (empty) config file 'file:/D:/LogicBig/example-projects/spring-boot/boot-customizing-autoconfig/target/classes/application.properties' (classpath:/application.properties) for profile default
2017-01-02 21:15:17.384  INFO 5704 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2f0a87b3: startup date [Mon Jan 02 21:15:17 CST 2017]; root of context hierarchy
2017-01-02 21:15:18.032  INFO 5704 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2017-01-02 21:15:18.047 DEBUG 5704 --- [           main] utoConfigurationReportLoggingInitializer :


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


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

   GenericCacheConfiguration matched:
      - Cache org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration automatic cache type (CacheCondition)

   JmxAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.jmx.export.MBeanExporter' (OnClassCondition)
      - @ConditionalOnProperty (spring.jmx.enabled=true) matched (OnPropertyCondition)

   JmxAutoConfiguration#mbeanExporter matched:
      - @ConditionalOnMissingBean (types: org.springframework.jmx.export.MBeanExporter; SearchStrategy: current) did not find any beans (OnBeanCondition)

   JmxAutoConfiguration#mbeanServer matched:
      - @ConditionalOnMissingBean (types: javax.management.MBeanServer; SearchStrategy: all) did not find any beans (OnBeanCondition)

   JmxAutoConfiguration#objectNamingStrategy matched:
      - @ConditionalOnMissingBean (types: org.springframework.jmx.export.naming.ObjectNamingStrategy; SearchStrategy: current) did not find any beans (OnBeanCondition)

   NoOpCacheConfiguration matched:
      - Cache org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration automatic cache type (CacheCondition)

   PropertyPlaceholderAutoConfiguration#propertySourcesPlaceholderConfigurer matched:
      - @ConditionalOnMissingBean (types: org.springframework.context.support.PropertySourcesPlaceholderConfigurer; SearchStrategy: current) did not find any beans (OnBeanCondition)

   RedisCacheConfiguration matched:
      - Cache org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration automatic cache type (CacheCondition)

   SimpleCacheConfiguration matched:
      - Cache org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration automatic cache type (CacheCondition)


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)

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

 ...............................
 ....................


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

    None


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

    org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration

    org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration

    org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration

    org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration



2017-01-02 21:15:18.058  INFO 5704 --- [       Thread-1] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@2f0a87b3: startup date [Mon Jan 02 21:15:17 CST 2017]; root of context hierarchy
2017-01-02 21:15:18.059  INFO 5704 --- [       Thread-1] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown

In the output above

  • Positive matches:@Conditional condition is true, configuration class is loaded by Spring container.
  • Negative matches: @Conditional condition is false, configuration class is not loaded by Spring container.
  • Exclusions: Application side explicitly excludes loading configuration
  • Unconditional classes: Autoconfiguration classes do not contain conditions at any class level, that is, classes are always loaded automatically.

Prohibit auto-configuration for specific classes

@EnableAutoConfiguration(exclude = {JmxAutoConfiguration.class})
public class ExcludeConfigExample {

    public static void main (String[] args) {
         //just doing this programmatically for demo
         String[] appArgs = {"--debug"};

        SpringApplication app = new SpringApplication(ExcludeConfigExample.class);
        app.setBannerMode(Banner.Mode.OFF);
        app.setLogStartupInfo(false);
        app.run(appArgs);
    }
}

output


  .............

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


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

   GenericCacheConfiguration matched:
      - Cache org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration automatic cache type (CacheCondition)

   NoOpCacheConfiguration matched:
      - Cache org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration automatic cache type (CacheCondition)

   PropertyPlaceholderAutoConfiguration#propertySourcesPlaceholderConfigurer matched:
      - @ConditionalOnMissingBean (types: org.springframework.context.support.PropertySourcesPlaceholderConfigurer; SearchStrategy: current) did not find any beans (OnBeanCondition)

   RedisCacheConfiguration matched:
      - Cache org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration automatic cache type (CacheCondition)

   SimpleCacheConfiguration matched:
      - Cache org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration automatic cache type (CacheCondition)


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:
-----------

    org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration


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

    org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration

    org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration

    org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration

    org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration

Posted by Vbabiy on Mon, 22 Jul 2019 20:05:06 -0700