[source code analysis] I don't know the details of automatic configuration, let alone you can spring boot.

Compared with spring, one of the most important characteristics of spring boot is automatic configuration, which makes the Convention larger than the configuration idea successfully implemented. XXX spring boot starter a series of bootstrappers can be used out of the box, or only need a few configurations (for beginners) because the default automatic configuration has been made.

Autoconfig initializes some configurations at the beginning, and provides access to modify the configuration.

Overall structure

Spring boot autoconfigure package is a very important package in spring boot starter, which provides automatic configuration function and sets default configuration for common dependency.

rely on

There are three types of packages it depends on:

  • Basic package: spring boot
  • Optional function dependency package: a common dependency package with default configuration. It is provided by the user in actual use.
  • Test package

Optional function dependency packages include spring data redis, validator, thmeleaf, websocket, etc. Here are a few examples to explain.

principle

@EnableAutoConfiguration

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
  /**
   *  When the corresponding property of this name is true, auto configuration is enabled.
   */
  String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
  
  /**
   *  Classes to exclude (usually used when the class is under the classpath)
   */
  Class<!--?-->[] exclude() default {};

  /**
   *  Class name to exclude (used when this class is not in the classpath)
   */
  String[] excludeName() default {};
}

@AutoConfigurationPackage

Register the package to which the class using this annotation belongs as a spring bean. The bean name of this spring bean is AutoConfigurationPackages. beanClass is BasePackages.

AutoConfigurationImportSelector

Automatic configuration selector, select which classes to configure automatically.

selectImports

Core method: String[] selectImports(AnnotationMetadata annotationMetadata), which returns the full class name array to be automatically configured. Classes that need to be automatically configured meet the following conditions:

  1. The class whose key is org.springframework.boot.autoconfigure.EnableAutoConfiguration in META-INF/spring.factories
  2. @The class represented by the exclude and excludeName properties in the EnableAutoConfiguration annotation, and the class set in spring.autoconfigure.exclude in the configuration (throw exception if the class path exists, but step 1 does not exist)
  3. Meet the conditions including three kinds of annotations: OnBeanCondition (such as ConditionalOnBean, ConditionalOnMissingBean), OnClassCondition (such as ConditionalOnClass, ConditionalOnMissingClass), OnWebApplicationCondition (such as ConditionalOnWebApplication, ConditionalOnNotWebApplication)

Finally, the AutoConfigurationImportEvent event event is activated.

getImportGroup and DeferredImportSelector.Group

Group results from different importselectors

Order of automatic configuration

  • AutoConfigurationSorter
  • @AutoConfigureOrder
  • @AutoConfigureBefore
  • @AutoConfigureAfter

AutoConfigurationSorter is the logic of specific control sorting @AutoConfigureOrder is an auto configuration specific variant of @ Order. Therefore, @ AutoConfigureOrder can be used when you need to set the Order of your own configuration. Controls the absolute Order of application configuration classes. @AutoConfigureBefore and @ AutoConfigureAfter control the relative order of application configuration classes.

The specific training sequence is as follows:

  1. Sort alphabetically by class name
  2. Sort by @ AutoConfigureOrder value (default: 0)
  3. Adjust the sorting according to @ autoconfigurebeefore and @ AutoConfigureAfter

Can @ Order control the Order of auto configuration classes?

@SpringBootApplication

In version 2.1.8.RELEASE, the combined annotation of this annotation is as follows:

// Omit unconcerned comments
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

The original @ Configuration has been changed to @ SpringBootConfiguration, with the following meanings:

  • So @ Configuration class
  • The class using this annotation provides the Spring Boot application. An application can only contain one @ SpringBootConfiguration class. Usually, @ SpringBootApplication is used.

AbstractDependsOnBeanFactoryPostProcessor

This class implements BeanFactoryPostProcessor, which will be executed at the right time during the spring boot process. Inherits this class, and dynamically determines which beans the specified type of bean should depend on through the constructor.

BackgroundPreinitializer

This class implements applicationlistener < springapplicationevent > This kind of function is to trigger early initialization in the background thread of time-consuming tasks, such as: ValidationInitializer, MessageConverterInitializer, Jackson initializer, CharsetInitializer, ConversionServiceInitializer, MBeanFactoryInitializer, etc.

@ImportAutoConfiguration

Import the autoconfig class. From the source point of view, they are all used for automatic configuration during testing. The annotation of this class is also configured in META-INF/spring.factories. The example is as follows:

@ImportAutoConfiguration
public @interface AutoConfigureDataJpa {}
org.springframework.boot.test.autoconfigure.orm.jpa.AutoConfigureDataJpa=\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration

Therefore, using the annotation AutoConfigureDataJpa is equivalent to importing classes such as JpaRepositoriesAutoConfiguration and DataSourceAutoConfiguration.

Use the following:

@BootstrapWith(DataJpaTestContextBootstrapper.class)
@ExtendWith(SpringExtension.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(DataJpaTypeExcludeFilter.class)
@Transactional
@AutoConfigureCache
@AutoConfigureDataJpa
@AutoConfigureTestDatabase
@AutoConfigureTestEntityManager
@ImportAutoConfiguration
public @interface DataJpaTest {
  // ...
}
@RunWith(SpringRunner.class)
@DataJpaTest
@TestPropertySource(properties = "spring.jpa.hibernate.use-new-id-generator-mappings=false")
public class DataJpaTestIntegrationTests {

	@Autowired
	private TestEntityManager entities;

	@Autowired
	private JdbcTemplate jdbcTemplate;

	@Autowired
	private ExampleRepository repository;

	@Autowired
	private DataSource dataSource;

	@Autowired
	private ApplicationContext applicationContext;

	@Test
	public void testEntityManager() {
		ExampleEntity entity = this.entities.persist(new ExampleEntity("spring", "123"));
		this.entities.flush();
		Object id = this.entities.getId(entity);
		ExampleEntity found = this.entities.find(ExampleEntity.class, id);
		assertThat(found.getName()).isEqualTo("spring");
	}
    
    // ...

Support for common tools

The above principle is the cornerstone of providing automatic configuration, but in practice, a lot of content can be used directly without any (or very little) configuration. On the one hand, each XXX spring boot starter contains spring boot autoconfigure and writes the automatic configuration logic. On the other hand, spring boot has been directly supported by the official spring boot autoconfigure package.

Example: gson auto configuration

The following classes are supported:

  • GsonProperties
  • GsonBuilderCustomizer
  • GsonAutoConfiguration

The GsonProperties class gets the configuration properties of Gson

@ConfigurationProperties(prefix = "spring.gson")
public class GsonProperties {
  private Boolean generateNonExecutableJson;
  private Boolean excludeFieldsWithoutExposeAnnotation;
  private Boolean serializeNulls;
  private String dateFormat;
  // ...
}
@FunctionalInterface
public interface GsonBuilderCustomizer {
	/**
	 * Custom GsonBuilder
	 */
	void customize(GsonBuilder gsonBuilder);
}

Use GsonProperties and GsonBuilderCustomizer in GsonAutoConfiguration (implemented in inner class)

@Configuration
@ConditionalOnClass(Gson.class)
@EnableConfigurationProperties(GsonProperties.class)
public class GsonAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public GsonBuilder gsonBuilder(List<gsonbuildercustomizer> customizers) {
        GsonBuilder builder = new GsonBuilder();
        customizers.forEach((c) -&gt; c.customize(builder));
        return builder;
    }

    @Bean
    @ConditionalOnMissingBean
    public Gson gson(GsonBuilder gsonBuilder) {
        return gsonBuilder.create();
    }

    @Bean
    public StandardGsonBuilderCustomizer standardGsonBuilderCustomizer(GsonProperties gsonProperties) {
        return new StandardGsonBuilderCustomizer(gsonProperties);
    }

    static final class StandardGsonBuilderCustomizer implements GsonBuilderCustomizer, Ordered {

        private final GsonProperties properties;

        StandardGsonBuilderCustomizer(GsonProperties properties) {
            this.properties = properties;
        }

        @Override
        public int getOrder() {
            return 0;
        }

        @Override
        public void customize(GsonBuilder builder) {
         // ...
        }

Public number: yifeixi (focus on the in-depth learning of Java knowledge, from source code to principle, systematic and orderly learning)

</gsonbuildercustomizer></springapplicationevent>

Keywords: Programming Spring JDBC Redis Hibernate

Added by zemerick on Thu, 17 Oct 2019 04:55:14 +0300