Usually we use SpringBoot development often use some third-party JAR packages, and usually just introduce an XXX-StarterJAR package has all the functions, exactly what is the principle? To see how this works, we can start by making our own Starter, which will be quite helpful to use some of the third frameworks in depth.

SpringBoot Starter development specification

The SpringBoot official website documents refer to the following specifications:

  • 1, naming usespring-boot-starter-xxx, includingxxxIs our specific package name if integratedSpring CloudUse thespring-cloud-starter-xxx
  • 2, usually need to prepare twojarFiles, one of which contains no code and is only responsible for importing the relevant JAR files, and the other contains the core code

For example, the starter integrated with NacOS and Spring Cloud is shown below:

For more on the Starter specifications, check out the documentation on the official website

Starter development steps

First of all, we should first understand the mechanism of Springboot loading third-party Starter, for details, please refer to another small article Springboot boot source code analysis and related skills to learn

  • 1. Create a new oneMavenThe project, we call itstudy-spring-boot-starter

  • Introduce related dependencies
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> </dependencies> <dependencyManagement> <! <dependency> <groupId>org.springframework.boot</groupId> The < artifactId > spring - the boot - dependencies < / artifactId > < version > 2.1.0. RELEASE < / version > <type>pom</type>
    		<scope>import</scope>
    	</dependency>
    </dependencies>
</dependencyManagement>
Copy the code

Since we need the annotations provided by Springboot and the automatic configuration provided by Springboot, we have to introduce two dependencies, spring-boot-autoconfigure and spring-boot-dependencies.

  • 3. Create our own auto-configuration class

In general, we may think when springboot start inject some beans in advance, at this point, we want to own automatic configuration class, new xxxxEnableAutoConfiguration generally adopted.

The following our new StudyStarterAutoConfiguration. Java

package com.example.mystarter.config; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.example.mystarter.other.Student; /** * holds our configuration class, which is used to configure our custom bean. Since this is a configuration class, * * @author jiawei Huang * @since August 23, 2019 * @version 1.0 */ @configuration // We import custom configuration class, for the use of the current class @ EnableConfigurationProperties (StudentConfigProperties. Class) / / when there is a class, This automatic configuration class will only take effect, this can be used outside of the String class name @ ConditionalOnClass (Student. Class) / / only when the web application this will only take effect @ ConditionalOnWebApplication automatic configuration class Public class StudyStarterAutoConfiguration {/ * * * when there study. Config. The enable =trueThe Student bean takes effect only when the Student bean is configuredreturn
     */
    @Bean
    @ConditionalOnProperty(prefix = "study.config", name = "enable", havingValue = "true")
    public Student defaultStudent(StudentConfigProperties studyConfigProperties) {
    	Student student = new Student();
    	student.setAge(studyConfigProperties.getAge());
    	student.setName(studyConfigProperties.getName());
    	returnstudent; }}Copy the code

@configuration Declares this class to be a Configuration class

@ EnableConfigurationProperties mean, will brackets as specified by the type of injection container become a bean object, because in general, For example, the default springBoot package scan path is xxxxxxapplication.java and all its subpackages, but some third-party JAR beans are obviously not scannable. This annotation comes in handy. Of course, you might say, I’ll just use @ComponentScan. The difference between these two annotations is: @ ComponentScan premise is you want bean bean existing in the container, and @ EnableConfigurationProperties want let container automatically discover your class and register as a bean.

Springboot provides a number of @condition annotations to indicate what to do when something is true or not.

@ ConditionalOnClass refers to when there is a class, this automatic configuration class StudyStarterAutoConfiguration will only take effect, we might ask, we sometimes want to rely on a third-party bean, To come into force StudyStarterAutoConfiguration do (such as mybatis starter source need sqlsessionfactorybean), don’t panic, @ ConditionalOnClass also allows us to specify the full path string, For example the @ ConditionalOnClass (” com. XXX. XXX “)

@ ConditionalOnWebApplication said when the current application is a web servlet applications, configuration class to take effect. This also explains why springBoot source code springApplication.java does application inference.

@SuppressWarnings({ "unchecked"."rawtypes"}) public SpringApplication(ResourceLoader resourceLoader, Class<? >... primarySources) { this.resourceLoader = resourceLoader; Assert.notNull(primarySources,"PrimarySources must not be null"); this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); / / here will do that this. WebApplicationType = webApplicationType. DeduceFromClasspath ();setInitializers((Collection) getSpringFactoriesInstances(
			ApplicationContextInitializer.class));
	setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
	this.mainApplicationClass = deduceMainApplicationClass();
}
Copy the code
  • 4. Let’s create a new oneStudentConfigProperties.java, which states which configuration items can be configured by users of the starter.
package com.example.mystarter.config; import org.springframework.boot.context.properties.ConfigurationProperties; /** * configuration item ** @author jiawei Huang * @since August 23, 2019 * @version 1.0 */ @configurationProperties (prefix ="study.config") public class StudentConfigProperties { private int age; private String name; / * * * @return the age
	 */
	public int getAge() {
		return age;
	}

	/**
	 * @param age the age to set
	 */
	public void setAge(int age) { this.age = age; } / * * * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "StudentConfigProperties [age=" + age + ", name=" + name + "]"; }}Copy the code
  • 5, inresourcesCreate a new one in the directoryMETA-INFDirectory and create onespring.factoriesfile
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
 com.example.mystarter.config.StudyStarterAutoConfiguration
Copy the code

Our automatic configuration entry class, Springboot will scan this file, and the scanning mechanism can see another blog post written by the small

Three, use our ownStarter

  • 1. Let’s create another SpringBoot project and introduce the new onestarter
< the dependency > < groupId > com. Example < / groupId > < artifactId > study < / artifactId > < version > 0.0.1 - the SNAPSHOT < / version > </dependency>Copy the code

Let’s create a new interface to test the usefulness of our starter. The code is as follows:

package com.example.demo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.example.mystarter.config.StudentConfigProperties; import com.example.mystarter.other.Student; /** ** @author jiawei Huang * @since 2019年8月19日 * @version 1.0 */ @restController Public Class MyController { @Autowired private Student student; @Autowired private StudentConfigProperties studentConfigProperties; @RequestMapping("/getStudent")
	private String getStudent() {
		return "name=[" + student.getName() + "],age=[" + student.getAge() + "],studentConfigProperties=["
				+ studentConfigProperties + "]"; }}Copy the code

Start our demo project, then access our interface, and the result is as follows:

Well, our starter production to this end, in fact, very simple, I suggest that on the basis of learning to make, look at the source code of other frameworks to verify, it is best to also start to achieve the following, maybe later we also need to provide a starer for others to use it. If you have any questions, please feel free to comment. Thank you for reading.