Write a Starter by hand

foreword

In order to make up for the shortcomings of java's upward class loading mechanism: the upper layer provides interfaces, and the specific implementation is provided by subclasses; in order to load this method into the java virtual machine, java provides a SPI mechanism (service provider interface), which can load There are many schemes for class loading by using this mechanism to implement classes that cannot be loaded by the class loading mechanism, such as jdbc loading Driver, Dubbo's SPI mechanism, Spring's automatic assembly, etc. Next, a Starter will be encapsulated and then referenced by another service. When the service starts, a Starter will be automatically assembled through the @Import(AutoConfigurationImportSelector.class) annotation under EnableAutoConfiguration in SpringBootApplication of SpringBoot.

Write a Starter by hand

First, you need to build a multi-moudle project. Under this project, create two modules, one is redission-spring-boot-starter and the other is spring-boot-demo that refers to the starter. The specific project structure is shown in the figure below. The following describes how to build These two projects;

redission-spring-boot-starter

1. pom file

The redisson dependency in the pom file, the specific content is as follows

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>2.1.6.RELEASE</version>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.13.2</version>
</dependency>

2. Create a META-INF directory under the resource directory, and create a spring-factories file under the directory. The content of the file is composed of two parts, which is actually equivalent to a key structure.

key是:org.springframework.boot.autoconfigure.EnableAutoConfiguration

value is the specific automatic configuration class: com.yangfan.redissionspringbootstarter.RedissonAutoConfiguration

The key and value are separated by =\, the specific content is as follows

org.springframework.boot.autoconfigure.EnableAutoConfiguration =\
com.yangfan.redissionspringbootstarter.RedissonAutoConfiguration

3、RedissonProperties

RedissonProperties is a class that reads configuration information in yml or apollo, the specific content is as follows:

@ConfigurationProperties(prefix = "yang.redisson")
public class RedissonProperties {
    private String host = "localhost";
    private int port = 6379;
    private int timeout;// 超时时间
    private boolean ssl;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public int getTimeout() {
        return timeout;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public boolean isSsl() {
        return ssl;
    }

    public void setSsl(boolean ssl) {
        this.ssl = ssl;
    }
}

4. RedissonAutoConfiguration is a configuration class that automatically assembles redission, the specific content is as follows

@Configuration
//条件装配,用于控制bean是否被加载
@ConditionalOnClass(Redisson.class)
//RedissonProperties注入到Spring ioc容器中
@EnableConfigurationProperties(RedissonProperties.class)
public class RedissonAutoConfiguration {

    @Bean
    public RedissonClient redissonClient(RedissonProperties redissonProperties){
        Config config =  new Config();
        String prefix = "redis://";
        if (redissonProperties.isSsl()){
            prefix = "rediss://";
        }
        config.useSingleServer().setAddress(prefix+redissonProperties.getHost()+":"+redissonProperties.getPort()).setConnectTimeout(redissonProperties.getTimeout());
        return Redisson.create(config);
    }
}

spring-boot-demo

1. First, redission-spring-boot-starter must be introduced in the pom file. The specific content of the pom file is as follows

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.3.1.RELEASE</version>
</dependency>

<dependency>
    <groupId>com.example</groupId>
    <artifactId>redission-spring-boot-starter</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

2. Configure the domain name and port required by redis in the application.properties file

a.redisson.host=127.0.0.1 
a.redisson.port=6379

3. Write a controller to verify whether the automatic assembly is successful

@RestController
@RequestMapping
public class RedisController {

    @Autowired
    private RedissonClient redissonClient;

    @GetMapping("/test")
    public String test(){
        RBucket bucket = redissonClient.getBucket("name");
        if(bucket.get() == null){
            bucket.set("com.yang.redisson");
        }else {
            bucket.expire(1, TimeUnit.SECONDS);
        }
        return bucket.get()+"";
    }

}

Before enabling the service, you need to install redission-spring-boot-starter first, so that it can be referenced by the second service. If the install reports Unable to find main class, you need to remove the build of redission-spring-boot-starter;

 Seeing the following information through the http request proves that the automatic assembly is successful

SPI principle analysis

First, let's look at this method: getAutoConfigurationEntry This method is to get the content in META-INF/spring.factories and load it into the java virtual machine;

org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getAutoConfigurationEntry

Next, let's take a look at the getCandidateConfigurations method, the core of which is the loading method: loadSpringFactories

 

 

Guess you like

Origin blog.csdn.net/weixin_38829588/article/details/125983763