This series is divided into five parts
1. How are @Component, @service, etc annotations parsed
2. @enable Driver mechanism
3. @enableAutoConfiguration Processing logic
4. Spring, springBoot event
5. Write a Springboot starter in just four steps

The introduction

Whenever you use Springboot, you will definitely use a variety of Spring-boot-starter. Write a spring-boot-starter
, only 4 steps. So let’s write a starter that will print the method execution time in the log.


The first step is to create a Maven project

When using spring-boot-starter, you can find that some projects are named xx-spring-boot-starter and others
Spring-boot-starter-xx, what’s the fancy about the name of this project?
Excerpted from the official SpringBoot documentation:

Do not start your module names with spring-boot, even if you use a different Maven groupId. We may offer official support for the thing you auto-configure in the future.

As a rule of thumb, you should name a combined module after the starter.

From this paragraph, you can see the unspoken naming rule of spring-boot-starter.
Latent rule of naming
Spring-boot-starter-xx is the official Springboot starter
Xx-spring-boot-starter is a third-party extension starter
The function of printing method execution time requires aop, which our project is called
Aspectlog – spring – the boot – the starter.
The poM files for the project are as follows:
<? 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 > org. Example < / groupId > < artifactId > aspectlog - spring - the boot - starter < / artifactId > < version > 1.0.2 < / version > < the parent > <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.15.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-starter-aop</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional>
        </dependency>
    </dependencies>

</project>Copy the code


The spring-boot-configuration-processor is described in the Official springBoot documentation.


Spring Boot uses an annotation processor to collect the conditions on auto-configurations in a metadata file ( META-INF/spring-autoconfigure-metadata.properties ). If that file is present, it is used to eagerly filter auto-configurations that do not match, which will improve startup time. It is recommended to add the following dependency in a module that contains auto-configurations:

<dependency>
<groupId> org.springframework.boot </groupId>
<artifactId> spring-boot-autoconfigure-processor </artifactId>
<optional> true </optional>
</dependency>


The short answer is
When writing the starter, configure it in the POM
Spring – the boot – autoconfigure – processor,
Configuration class conditions are automatically collected at compile time and written to one
The meta-inf/spring – autoconfigure – metadata. The properties.


Step 2 write the automatic configuration logic

All kinds of condition


type annotations instructions
Class Conditions
Class conditional annotation
@ConditionalOnClass

Under the current classpath

Only the specified class is loaded

@ConditionalOnMissingClass

Under the current classpath

No specified class is loaded

Bean Conditions
Bean conditional annotations
@ConditionalOnBean

The current container contains

Specify that the bean is loaded

@ConditionalOnMissingBean

None in the current container

Specify that the bean is loaded

Property Conditions
Environment variable condition
Notes (including configuration files)
@ConditionalOnProperty
The prefix prefix
The name of the name
havingValue
Used to match the value of a configuration item
matchIfMissing
The specified configuration item is not found
The default value of
Resource
Conditions

Notes on Resource Conditions

@ConditionalOnResource Only a specified resource is loaded
Web Application Conditions
Web Condition Annotations
@ConditionalOnWebApplication Only web loads
@ConditionalOnNotWebApplication It’s not web that loads
SpEL Expression Conditions @ConditionalOnExpression The SpEL expression is loaded
This time we’ll use @conditionalonProperty. If there is aspectLog.enable=true in the configuration file, our configuration class will be loaded.
Let’s start writing the auto-configuration class


2.1. Define AspectLog annotations for annotating methods that require printing execution times.

package com.shanyuan.autoconfiguration.aspectlog; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * class_name: ScheduleManage * describe: used to control the start and stop of scheduled tasks * 2018/11/10 18:45 **/ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface AspectLog { }Copy the code


2.2 Defining classes corresponding to configuration files

package com.shanyuan.autoconfiguration.aspectlog;
import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("aspectLog")
public class AspectLogProperties {
    private boolean enable;
    public boolean isEnable() {
        return enable;
    }
    public void setEnable(boolean enable) {
        this.enable = enable; }}Copy the code


2.3 Defining automatic configuration Classes


package com.shanyuan.autoconfiguration.aspectlog;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.*;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.core.PriorityOrdered;

@Aspect
@EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true)
@Configuration
@ConditionalOnProperty(prefix = "aspectLog", name = "enable",
                     havingValue = "true", matchIfMissing = true)
public class AspectLogAutoConfiguration implements PriorityOrdered {

    protected Logger logger = LoggerFactory.getLogger(getClass());

@Around("@annotation(com.shanyuan.autoconfiguration.aspectlog.AspectLog) ") public Object isOpen(ProceedingJoinPoint thisJoinPoint) throws Throwable {// Execution method name String taskName = thisJoinPoint.getSignature() .toString().substring( thisJoinPoint.getSignature() .toString().indexOf(""), 
                    thisJoinPoint.getSignature().toString().indexOf("("));
        taskName = taskName.trim();
        long time = System.currentTimeMillis();
        Object result = thisJoinPoint.proceed();
        logger.info("method:{} run :{} ms", taskName, 
                            (System.currentTimeMillis() - time));
        return result;
    }
    @Override
    public int getOrder() {// Ensure that the transaction and other facets are executed firstreturnInteger.MAX_VALUE; }}Copy the code


Configuration class brief description:
@ConditionalOnProperty(prefix = “aspectLog”, name = “enable”,havingValue = “true”, matchIfMissing = true)
Enable is enabled when aspectLog.enable=true in the configuration file or if aspectLog.enable is not set in the configuration file.


The third step meta-inf/spring. Factories

Meta-inf/Spring. factories are spring factories in which classes defined are automatically loaded. Multiple configurations are separated by commas and newlines are \
If you are interested, check out these two blogs:
2.@Enable Driver principle (Setting connection)
3.@EnableAutoConfiguration Processing logic (setting up connections)
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.shanyuan.autoconfiguration.aspectlog.AspectLogAutoConfigurationCopy the code


Step 4: Pack test

This is our final directory structure

In IDEA, MVN intall is performed


Once packaged, it is introduced for testing in poMs in other projects


The resources
Docs. Spring. IO/spring – the boot…