SpringBoot fundamentals

SpringBoot can help us make better use of Spring and configure a running Spring application faster.

SpringBoot automatic configuration is the entrance to the @ EnableAutoConfiguration annotations, the annotations by @ Import annotations Import AutoConfigurationImportSelector, In this class implements the meta-inf/spring. The factories in the org. Springframework. Boot. Autoconfigure. EnableAutoConfiguration attribute specifies all the configuration, Such as org. Springframework. Boot. Autoconfigure. Cache. CacheAutoConfiguration.

// File: spring-boot-autoconfigure-2.1.3.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,\
Copy the code

In CacheAutoConfiguration, the conditional annotation @conditionalonxxx and the @import annotation are used to automatically configure related beans for caching functionality.

// File: spring-boot-autoconfigure-2.1.3. release-sources.jar! /org/springframework/boot/autoconfigure/cache/CacheAutoConfiguration.java @Configuration @ConditionalOnClass(CacheManager.class) @ConditionalOnBean(CacheAspectSupport.class) @ConditionalOnMissingBean(value = CacheManager.class, name ="cacheResolver") @EnableConfigurationProperties(CacheProperties.class) @AutoConfigureAfter({ CouchbaseAutoConfiguration.class, HazelcastAutoConfiguration.class, HibernateJpaAutoConfiguration.class, RedisAutoConfiguration.class }) @Import(CacheConfigurationImportSelector.class) public class CacheAutoConfiguration { @Bean @ConditionalOnMissingBean public CacheManagerCustomizers cacheManagerCustomizers( ObjectProvider<CacheManagerCustomizer<? >> customizers) {return new CacheManagerCustomizers(
				customizers.orderedStream().collect(Collectors.toList()));
	}
Copy the code

Implement your own AutoConfiguration

During actual development, we may need to integrate third-party libraries that are either in-house or not officially supported by Spring into our project. But for reuse, it is best to follow SpringBoot’s automatic configuration.

Step 1: Introduce Spring official dependencies

Pom files for the project:

<? xml version="1.0" encoding="UTF-8"? > <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> < modelVersion > 4.0.0 < / modelVersion > <! <groupId>geektime.spring. Hello </groupId> < artifactId > geektime - spring - the boot - autoconfigure < / artifactId > < version > 0.0.1 - the SNAPSHOT < / version > <name>geektime-spring-boot-autoconfigure</name> <description>Demo projectforSpring Boot < / description > < properties > < Java version > 1.8 < / Java version > < spring - the boot version > 2.1.3. RELEASE < / spring - the boot. Version > < / properties > <! <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version>
				<type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <! <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <! Hello </groupId> <artifactId> Greeting </artifactId> <version>0.0.1-SNAPSHOT</version> <scope>provided</scope> </dependency> </dependencies> </project>Copy the code

Step 2: Write Java Configuration and add conditional annotations

Conditional comments supported by Spring:

  • Conditional annotation @Conditional
  • @ ConditionalOnClass class conditions, @ ConditionalOnMissingClass
  • Attribute condition@conditionalonProperty
  • @ ConditionalOnBean Bean conditions, @ ConditionalOnMissingBean, @ ConditionalOnSingleCandidate
  • Conditioncondition@conditionalonResource
  • @ ConditionalOnWebApplication Web applications use conditions, @ ConditionalOnNotWebApplication
  • Other conditions @conditionalonexpression, @conditionalonJava, @conditionalonjndi

The Java Configuration code is as follows:

@Configuration
@ConditionalOnClass(GreetingApplicationRunner.class)
public class GreetingAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean(GreetingApplicationRunner.class)
    @ConditionalOnProperty(name = "greeting.enabled", havingValue = "true", matchIfMissing = true)
    public GreetingApplicationRunner greetingApplicationRunner() {
        returnnew GreetingApplicationRunner(); }}Copy the code

Step 3: Locate automatic configuration

Under the meta-INF directory of the current project, create a Spring. factories file like this:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
geektime.spring.hello.greeting.GreetingAutoConfiguration
Copy the code

Step 4: Define the order in which the automatic configuration is executed

The main notes are:

  • @AutoConfigureBefore
  • @AutoConfigureAfter
  • @AutoConfigureOrder

Generally, this is not required. For details, see the official Spring automatic configuration.

How to implement SpringBoot in older versions of Spring that do not support SpringBoot

If you implement springboot-like automatic configuration in older versions of Spring, you need to use Spring’s extension point mechanism. For details, see the Spring framework extension point blog.

Add a Configuration:

@Configuration
public class GreetingAutoConfiguration {
    @Bean
    public static GreetingBeanFactoryPostProcessor greetingBeanFactoryPostProcessor() {
        returnnew GreetingBeanFactoryPostProcessor(); }}Copy the code

Define a BeanFactoryPostProcessor that implements similar conditional annotations:

@Slf4j
public class GreetingBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        boolean hasClass = ClassUtils.isPresent("geektime.spring.hello.greeting.GreetingApplicationRunner",
                GreetingBeanFactoryPostProcessor.class.getClassLoader());
        if(! hasClass) { log.info("GreetingApplicationRunner is NOT present in CLASSPATH.");
            return;
        }

        if (beanFactory.containsBeanDefinition("greetingApplicationRunner")) {
            log.info("We already have a greetingApplicationRunner bean registered.");
            return;
        }

        register(beanFactory);
    }

    private void register(ConfigurableListableBeanFactory beanFactory) {
        if (beanFactory instanceof BeanDefinitionRegistry) {
            GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
            beanDefinition.setBeanClass(GreetingApplicationRunner.class);

            ((BeanDefinitionRegistry) beanFactory)
                    .registerBeanDefinition("greetingApplicationRunner",
                            beanDefinition);
        } else {
            beanFactory.registerSingleton("greetingApplicationRunner", new GreetingApplicationRunner()); }}}Copy the code

The resources

  1. Extension points of the Spring framework
  2. Spring Family bucket video course SpringBoot
  3. Spring family bucket course code