This article has participated in the call for good writing activities, click to view: back end, big front end double track submission, 20,000 yuan prize pool waiting for you to challenge!

1. Configure the development environment

1. Create a Maven project

After creating a Maven project, you need to add a compilation environment to prevent each update to Maven from automatically changing the language level of the project to Java5 and failing to compile.

<profile>
  <id>The JDK 1.8 ‐</id>
  <activation>
    <activeByDefault>true</activeByDefault>
    <jdk>1.8</jdk>
  </activation>
  <properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
  </properties>
</profile>
Copy the code

2. Add dependencies to Maven

Starting with the most basic dependencies are the parent parent project and the Web starter.

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9. RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
Copy the code

Obviously the parent project is for version control. Why? Let’s trace the parent project, go to the parent project’s pox. XML and see the following configuration.

<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-dependencies</artifactId>
		<version>1.5.9. RELEASE</version>
		<relativePath>. /.. /spring-boot-dependencies</relativePath>
	</parent>
Copy the code

Continuing to trace the parent project, you can see the following.

<properties>
		<! -- Dependency versions -->
		<activemq.version>5.14.5</activemq.version>
		<antlr2.version>2.7.7</antlr2.version>
		<appengine-sdk.version>1.9.59</appengine-sdk.version>
		<artemis.version>1.5.5</artemis.version>
		<aspectj.version>1.8.13</aspectj.version>
		<assertj.version>server</assertj.version>
		<atomikos.version>3.9.3</atomikos.version>. .</properties>
Copy the code

Ok, now we finally get to the source, these properties are used to specify the version of the framework that SpringBoot integrates, so we only need to manage the version of SpringBoot, and we don’t have to worry about the various components that are packaged inside, it’s configured for us. But we can continue to customize it ourselves, and we’ll talk about that later.

As you can see, the other starter is the web starter. In Fact, in SpringBoot, the starter name is very standard. What is a starter? In simple terms, Springboot is used to integrate each framework package, we need what framework what function to add these corresponding starter in Springboot can enjoy the pleasure out of the box!

2. Pry into the main process

With this minimal configuration done, we are ready to write the startup code, which is very simple and only a few lines long.


// @springBootApplication to annotate a main program class
@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {
        // Spring starts!SpringApplication.run(MainApplication.class,args); }}Copy the code

It’s amazing that we’ve written a springBoot application that works perfectly. We’ve just written a comment and a line of code. Why is it so simple?

1. @ SpringBootApplication annotation

The first thing you can see is that this is a composite annotation, which says something like this:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
Copy the code

Let’s look at them one by one:

  1. @SpringBootConfigurationThis annotation is a notation that this is aSpringBootConfiguration class, that is, can be carried outSpringBootConfiguration class is equivalent to configuration file, we need to have this equivalent concept. And then we open up this annotation and it’s insidespringA Java Config annotation for@ConfigurationSo this is actuallySpringBoot The main configuration class of.
  2. @EnableAutoConfigurationIt’s used to turn on autoconfiguration, which isSpringBootAt the heart of what actually works in the endSpring - the boot - configuration - processor - 1.5.9. The jarThis package is working, as will be explained later. Look at what’s in this note!
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
Copy the code

Two notes:

1.@AutoConfigurationPackage

The first is to automatically guide the component’s annotations. The bottom line calls the Spring bottom line annotation (@import) to Import a component into the container. Is @ Import (AutoConfigurationPackages. The Registrar. The class) can see him into an automatic configuration package registry. Import is a low-level Spring annotation used to Import components. Then I’ll look at what this component does:

@Order(Ordered.HIGHEST_PRECEDENCE)
static class Registrar implements ImportBeanDefinitionRegistrar.DeterminableImports {

   @Override
   public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
      register(registry, new PackageImport(metadata).getPackageName()); // Get the package information in the metadata, and then import the component core inside these packages !!!!
   }

   @Override
   public Set<Object> determineImports(AnnotationMetadata metadata) {
      return Collections.<Object>singleton(newPackageImport(metadata)); }}Copy the code

If we set a breakpoint on the registered component, we will see that the package name calculated here is the package name of our main class. That is, we need to import the package of our main class and the corresponding component of the sub-package, our own component. So we have to put the other classes in other packages that are parallel to the main class, otherwise we can’t load them into the container.

2.@Import(EnableAutoConfigurationImportSelector.class)

The second is to import a Seletor component. Let’s take a look at the code of this component. It’s a simple method, but we found that it inherits from a class, so we need to look at the methods of the parent class.

public class EnableAutoConfigurationImportSelector  extends AutoConfigurationImportSelector{
          / /...
      }
Copy the code

Then we see a very important method in the parent class, selectImports, which completes our automatic configuration!

public String[] selectImports(AnnotationMetadata annotationMetadata) {
   if(! isEnabled(annotationMetadata)) {return NO_IMPORTS;
   }
   try {
      AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
            .loadMetadata(this.beanClassLoader);
      AnnotationAttributes attributes = getAttributes(annotationMetadata);
      List<String> configurations = getCandidateConfigurations(annotationMetadata,
            attributes);
      configurations = removeDuplicates(configurations);
      configurations = sort(configurations, autoConfigurationMetadata);
      Set<String> exclusions = getExclusions(annotationMetadata, attributes);
      checkExcludedClasses(configurations, exclusions);
      configurations.removeAll(exclusions);
      configurations = filter(configurations, autoConfigurationMetadata);
      fireAutoConfigurationImportEvents(configurations, exclusions);
      return configurations.toArray(new String[configurations.size()]);
   }
   catch (IOException ex) {
      throw newIllegalStateException(ex); }}Copy the code

You can see there’s a configurations variable in there and that’s some of the packages that we automatically configure. You can interrupt to see what’s inside.

The underlying component of this component is the various BeanFactories that we call the Ioc container in Spring, and then we import our auto-configuration class, xxxAutoConfiguration, That is, the contents of the spring-boot-configuration-processor-1.5.9.release.jar package.

Which xxxAutoConfiguration should be added to the container? So we need to look at a method. At the bottom of the Selector has a getCandidateConfigurations method, this method is to scan all packages below the meta-inf/spring. Factories file, The EnableAutoConfiguratio property in these files then automatically configures the component based on which xxxAutoConfiguration classes to import. Spring-boot-configuration-processor-1.5.9.release.jar

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
Copy the code

You can see that this is his auto-configuration mechanism!

2. Run method

At the bottom of this method is a new SpringApplication thing, which is clearly the real SpringBoot startup class. The last call to public ConfigurableApplicationContext run (String… Args) does a series of startup operations, but I won’t go into details. Then the class we passed in is placed in sources = new LinkedHashSet(); In this data structure. It doesn’t feel like much use.

So our SpringBoot application is ready to run. But we can’t access any pages, mainly because we don’t have controllers! Okay, so let’s write a simple controller.

3. Web interface development

@Controller // mark him as controller
@ResponseBody // Can return data
public class HelloController {
    @GetMapping("/hello") / / url mapping
    public String hello(a){
        return "Hello World!"; }}Copy the code

So at sign Controller, at sign ResponseBody we can combine these two annotations and use at sign RestController which is essentially a combination of these two annotations. The following @getMapping is the mapping of get requests, and corresponding to POST, PUT, and DELETE requests, which are specified by restful interfaces in different situations.

When we go to localhost:8080/hello, it says “Hello World!” !

4. Package the deployment

This is very easy to package and deploy in SpringBoot using a Maven plugin that we can package as jars instead of wars. This means that we can run the jar package directly using the java-jar command. Wait a minute! Don’t you need a Web container like Tomcat? Right! Since SpringBoot is embedded with Tomcat, there is no such thing as deploying to a Web container, so deployment is simple. Then we need to add a package plug-in.

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
Copy the code

Next, simply execute the package command in Maven to generate the JAR package in the target directory. And we can use java-jar to execute this JAR.

5. Resource directory structure

Directory structure in the Resources folder:

  • Static: Saves all static resources such as JS, CSS images.
  • Templates: Holds HTML templates for all template pages.
  • Application. properties: configuration file of the Spring Boot application.