“This is the 11th day of my participation in the Gwen Challenge in November. See details: The Last Gwen Challenge in 2021”

Why do we need to introduce a large number of starter to develop Java Web applications using the SpringBoot framework? For example, if we import Redis, we import spring-boot-starter-data-redis in Maven. As we all know, the core function of SpringBoot is automatic assembly and simplified configuration. We realize the function of SpringBoot automatic assembly through starter. So how do we build our own starter?

1 introduction

SpringBoot now accounts for almost half of Java, and its advantages are obvious. It simplifies the complex configuration of Spring through auto-assembly, and the inclusion of Tomcat allows us to start Web projects without having to configure Tomcat ourselves, which can greatly improve our development efficiency and code quality. As for why we import other dependencies as starter when building projects using the SpringBoot framework? In fact, these starte for us to implement the SpringBoot automatic assembly function, we will be together how to implement the automatic assembly function, how to build a SpringBoot starter application.

2 @ EnableConfigurationProperties automatic assembly

2.1 Create a Starter project

Create a project through Maven

Add the corresponding dependency to the POM file

<dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> < version > 1.18.22 < / version > < / dependency > < the dependency > < groupId > org. Springframework. Boot < / groupId > The < artifactId > spring - the boot - starter - web < / artifactId > < version > 2.5.6 < / version > < / dependency > < / dependencies >Copy the code

2.2 Creating an autowiring Bean

Using the @ EnableConfigurationProperties annotation

Create a class – this class finally can be assembled automatically by the configuration file, add annotations @ EnableConfigurationProperties when an error, because this is the need for the current object defined as a component of the Spring, But we’re not registered as a Spring Component with the @Component annotation.

/**
 * @author zhj
 */
@Data
@ConfigurationProperties(prefix = "com.zhj.vo.student")
public class Student {
​
    private Long id;
​
    private String name;
​
    private Integer age;
}
Copy the code

2.3 Automatic assembly class implementation

@Configuration is the class for which the Bean registration is required

@ EnableConfigurationProperties ({Student. Class}) will be registered in the Bean

/ automatic assembly class * * * * @ author ZHJ * / @ Configuration / / requires Bean registered @ EnableConfigurationProperties ({Student. Class}) / / Bean registration public class AutoConfiguration { }Copy the code

2.4 Write test items

Pom file import dependencies required for testing

<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> The < version > 2.5.6 < / version > < / dependency >Copy the code

Writing configuration files

Com: ZHJ: vo: student: id: 1 name: 'xiaoming' age: 12Copy the code

Writing test classes

/** * Automatic injection test class * @author ZHJ */ @runwith (springrunner.class) // junit4 test environment @webAppConfiguration // Start the Web runtime environment @ SpringBootTest (classes = AutoConfigApplication. Class) / / specified start class public class AutoConfigTest {@autowired @qualifier (" com.zhj.vo.student-com.zhj.vo.student ") // prefix - private student student; @Test public void test01() { System.out.println(student); }}Copy the code

You can see that the Bean was successfully injected into the Spring container through the configuration file, and you can get the Student object

Student(id=1, name=小明, age=12)

3 @import Implements automatic injection

The main purpose of the @import annotation is to inject beans into the Spring container

3.1 Mode I directly formulate the import of beans

Modify the classes required for automatic assembly

/** * auto-assembly class * @author ZHJ */ @configuration // @import ({student.class}) //Bean registration public class AutoConfiguration { }Copy the code

2 Modify the test class

/** * Automatic injection test class * @author ZHJ */ @runwith (springrunner.class) // junit4 test environment @webAppConfiguration // Start the Web runtime environment @ SpringBootTest (classes = AutoConfigApplication. Class) / / specified start class public class AutoConfigTest {@autowired private Student  student; @Test public void test01() { System.out.println(student); }}Copy the code

It is also possible to inject beans into the Spring container through configuration files

3.2 Method two Uses ImportSelector to inject beans

If there are many classes that need to be registered, the first approach lists all the beans that need to be injected

1 Create DefaultImportSelector to implement the ImportSelector interface

/** * @author zhj */ public class DefaultImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String[] {"com.zhj.vo.Student"}; }}Copy the code

Modify the classes required for automatic assembly

/ automatic assembly class * * * * @ author ZHJ * / @ Configuration / / requires Bean registered @ Import ({DefaultImportSelector. Class}) public class AutoConfiguration { }Copy the code

3.3 way three use ImportBeanDefinitionRegistrar inject beans

Above way are the Spring container is responsible for the registration of the Bean, we can put Bean ImportBeanDefinitionRegistrar themselves to the Spring container

1 create DefaultImportBeanDefinitionRegister ImportBeanDefinitionRegistrar interface

/** * @author zhj */ public class DefaultImportBeanDefinitionRegister implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Student.class); / / configuration bean registry. RegisterBeanDefinition (" studentInstance rootBeanDefinition); // Bean registration}}Copy the code

Modify the classes required for automatic assembly

/ automatic assembly class * * * * @ author ZHJ * / @ Configuration / / requires Bean registered @ Import ({DefaultImportBeanDefinitionRegister. Class}) to the public class AutoConfiguration { }Copy the code

4 Achieve automatic configuration across projects

All of the above autowaging implementations are done by injecting beans through the starter project configuration file and testing them in the Starter project. So how do we

4.1 Adding a Dependency

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

4.2 Compiling a Project

Compiling projects using Maven produces the spring-configuration-metadata.json file

{
  "groups": [
    {
      "name": "com.zhj.vo.student",
      "type": "com.zhj.vo.Student",
      "sourceType": "com.zhj.vo.Student"
    }
  ],
  "properties": [
    {
      "name": "com.zhj.vo.student.age",
      "type": "java.lang.Integer",
      "sourceType": "com.zhj.vo.Student"
    },
    {
      "name": "com.zhj.vo.student.id",
      "type": "java.lang.Long",
      "sourceType": "com.zhj.vo.Student"
    },
    {
      "name": "com.zhj.vo.student.name",
      "type": "java.lang.String",
      "sourceType": "com.zhj.vo.Student"
    }
  ],
  "hints": []
}
Copy the code

4.3 Modifying The Automatic assembly class Modified

Enable the autowiring class to inject beans automatically

/ automatic assembly class * * * * @ author ZHJ * / @ Configuration / / requires Bean registered @ Import ({DefaultImportBeanDefinitionRegister. Class}) to the public Class AutoConfiguration {// Automatic registration bean@bean (name = "Students") public List<String> getNameList() {List List = new ArrayList(); List. The add (" Ming "); List. The add (" little red "); List. The add (" xiao li "); return list; }}Copy the code

4.4 spring. Factories file

SRC /main/resources/ meta-INF /spring.factories

This file is the core file that supports automatic assembly of different files.

Add content to specify classes for autowiring

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.zhj.config.AutoConfiguration
Copy the code

4.5 Other Web Projects Spring-boot-auto-config-starter is introduced

<dependencies> <dependency> <groupId>com.zhj</groupId> <artifactId>spring-boot-auto-config-starter</artifactId> The < version > 1.0 - the SNAPSHOT < / version > < / dependency > < / dependencies >Copy the code

4.6 test

  • Write VO (Student) to the Web project

    /**
     * @author zhj
     */
    @Data
    @ConfigurationProperties(prefix = "com.zhj.vo.student")
    public class Student {
    ​
        private Long id;
    ​
        private String name;
    ​
        private Integer age;
    }
    Copy the code
  • Write the configuration to the Web project

    Com: ZHJ: vo: student: id: 1 name: 'xiaoming' age: 12Copy the code
  • Building test interfaces

    /** * @author zhj */ @RestController public class HelloController { @Autowired private Student student; @GetMapping("/hello") public String hello() { return "hello "+ student; }}Copy the code
  • The results of

5 concludes

In this article, we will build a simple Starter project for SpringBoot to understand the automatic assembly of SpringBoot. SpringBoot provides a variety of Bean assembly methods for developers. What we need to do is to understand these automatic assembly mechanisms and flexibly apply them to the development of enterprises. We can develop our own development starter and make full use of the advantages of SpringBoot so that our projects can also be easily configured. We inject the beans into the Spring container so that we can apply them flexibly. The spring.factories file is also a priority, allowing us to easily inject beans into the Spring container across projects.