Automatic configuration of SpringBoot

Why can springBoot be configured with 0?

This problem requires us to take a look at the SpringBoot source code, first take a look at the flowchart:

Graph TD A(comment SpringBootAapplication) --> B(comment EnableAutoConfiguration) B -->C(comment Import) Injection AutoConfigurationImportSelector. Class C) - > D (org. Springframework. Boot. Autoconfigure. AutoConfigurationImportSelector# selectImports method) D - > E (to find the file Meta-inf /spring.factories) E -->F(find the classes mapped by EnableAutoConfiguration in the file)Copy the code

==SpringBoot automatically scans for the meta-INF /spring.factories file in the classpath, loads the configuration file based on the configuration, and completes the automatic configuration ==

If you use springBoot and you rely on a JAR, the factories will automatically initialize the factories. If you use springBoot, you don’t need to use @enablexxx to enable the factories. The process is configured using the spring.factories file

Why is SrringBoot auto-configured?

Here’s an application scenario: there is A B project that references A project, but by default @SpringApplication only scans for beans in the classpath, so A project’s annotations cannot be scanned! One way to solve this problem is to configure A Scan annotation on project B. The other way is to have project A automatically configured when referred to by project B.

How do you write autoconfiguration?

Pom resources

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.1. RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
        </dependency>
    </dependencies>
Copy the code

1. Write a configuration class to map the parameter configuration in Application. yml, so that our custom components can complete some specific functions through configuration

Note: @ConfigurationProperties will be red in red for now because no configuration is specified

package com.my.properties;


import org.springframework.boot.context.properties.ConfigurationProperties;

/** * Configure the corresponding class *@author huangfu
 */
@ConfigurationProperties("example.service")
public class ExampleServiceProperties {
    private String prefix;
    private String suffix;

    public String getPrefix(a) {
        return prefix;
    }

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    public String getSuffix(a) {
        return suffix;
    }

    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }

    public ExampleServiceProperties(String prefix, String suffix) {
        this.prefix = prefix;
        this.suffix = suffix;
    }

    public ExampleServiceProperties(a) {}}Copy the code

ConfigurationProperties(“example.service”)== corresponds to the prefix of Application

== For example, ==

example:
  service:
    prefix: @ @
    suffix: # #
Copy the code

The configuration above corresponds to the configuration information class above

2. Write a service to accomplish the functionality we need

Here’s an example: the function is to add a prefix and suffix to the parameters passed in! Prefixes and suffixes can be configured using YML

package com.my.service;

/** * Add a custom prefix and suffix *@author huangfu
 */
public class ExampleService {

    private String prefix;
    private String suffix;

    public ExampleService(String prefix, String suffix) {
        this.prefix = prefix;
        this.suffix = suffix;
    }

    public String join(String content){
        returnprefix + content + suffix; }}Copy the code

3. Write configuration classes

package com.my.conf;

import com.my.properties.ExampleServiceProperties;
import com.my.service.ExampleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/ * * *@EnableConfigurationPropertiesAutomatic configuration is performed when the class is discovered in the CLASSPath. *@author huangfu
 */
@Configuration
@EnableConfigurationProperties(ExampleServiceProperties.class)
public class ExampleAutoConfigure {

    @Autowired
    private ExampleServiceProperties exampleServiceProperties;

    @Bean
    / * * *@ConditionalOnPropertyThis is triggered when yML is configured with example.service.enabled=true * the condition matches only if the BeanFactory does not contain the specified bean class and/or name */
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = "example.service" , value = "enabled" ,havingValue = "true")
    public ExampleService exampleService(a){
        return newExampleService(exampleServiceProperties.getPrefix(),exampleServiceProperties.getSuffix()); }}Copy the code

4. Final step

Create the meta-INF /spring.factories file in the ==resources== directory and configure the configuration class ExampleAutoConfigure into the spring.factories file

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.my.conf.ExampleAutoConfigure
Copy the code

reference

After packaging, reference in other projects

<dependency>
    <groupId>com.example</groupId>
    <artifactId>example-spring-boot-starter</artifactId>
    <version>1.0 the SNAPSHOT</version>
</dependency>

Copy the code

Configuring the configuration file

example:
  service:
    suffix: I am a suffix
    prefix: I am a prefix
    enabled: true
Copy the code

Direct reference where used

@Autowired
private ExampleService exampleService;

public String example(String content){
    return exampleService.join(content);
}
Copy the code

The results of

Words from the heart:

In business logic, if you encounter injection of this kind of requirements, we must not pervert, this kind of requirements out of CRUD, small companies of ordinary code farmers are difficult to meet, so must be well designed inside each logic code, so that it has better scalability, low coupling! When writing code, think more, draw more pictures, do not come up to the pat-pat-pat-write code, this habit I feel very bad!

Haha, the above is also the author’s heart, do not like spray! Stay tuned for the next article on SpringBoot’s autowiring principles! If the reader has good idea and suggestion, hope private chat author! Study together and make progress together!

If there is an error in the understanding of the article, you are welcome to talk to the bosses. Welcome to follow the author’s public account, progress together, learn together!