SpringBoot自己手写个starter

SpringBoot自定义starter
1.需求
2. 代码实现
3. 用到的注解
4.遇到的问题
1.需求
目前Java项目框架一般都是以SpringBoot作为脚手架来搭建的,具体什么原因就不用我在这里多说了吧。为了方便我们使用呢,它也封装了很多相关的starter组件,只要我们在项目中引入就行了。因为我们项目中用的是第三方插件Jongo来操作数据库MongoDB 的,所以这里我就尝试着吧Jongo封装成一个自定义starter。

2. 代码实现
1.首先我们需要创建一个mudule。我这里取名为spring-boot-starter-mongodb-jongo,大致如下:

pom.xml文件:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.8.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <artifactId>spring-boot-starter-mongodb-jongo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>spring-boot-starter-mongodb-jongo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongo-java-driver</artifactId>
            <version>3.12.3</version>
        </dependency>
        <dependency>
            <groupId>org.jongo</groupId>
            <artifactId>jongo</artifactId>
            <version>1.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.4.2</version>
                <configuration>
                    <skipTests>true</skipTests>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
pom文件设置了SpringBoot的版本,引入了Jongo和Mongo的一些依赖,版本的话可以自行修改。因为创建module时默认引入的是SpringBoot的插件,打包的时候会自动去寻找SpringBoot的启动类,所以这里需要把插件修改为maven 的一个插件maven-surefire-plugin。

接下来是配置代码:
首先定义一个属性类JongoAutoProperties,为了接收我们配置的一些mongodb的属性信息:

package org.springframework.boot.autoconfigure.data.mongodb;

import org.springframework.boot.context.properties.ConfigurationProperties;
import java.io.Serializable;
@ConfigurationProperties(
        prefix = "mongo"
)
public class JongoAutoProperties implements Serializable {
    private String host="127.0.0.1";    // 主库
    private int port=27017;      // 主库
    private String cluser="127.0.0.1"; // 副本集
    private int cport=27017;   //  副本集
    private String database;
    private String username;
    private String password;
    private boolean open=true; // 定义一个属性决定是否加载该组件

  省略get和set方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@ConfigurationProperties:加载SpringBoot属性文件application.properties中的属性配置.
因为mongodb有可能会设置副本集,所以我这里多定义了两个属性接受副本集的信息。
实际上应该定义一个list来存放数据库ip和端口,因为又可能会有很多个链接信息。

定义一个配置类JongoAutoConfig自动注入一些Bean对象

package org.springframework.boot.autoconfigure.data.mongodb;

import com.mongodb.*;
import org.jongo.Jongo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDatabaseFactory;

import java.util.ArrayList;
import java.util.List;

@Configuration
@ConditionalOnClass({Jongo.class,JongoTemplate.class})
@EnableConfigurationProperties({JongoAutoProperties.class})
@ConditionalOnProperty(
        prefix = "mongo",
        value = "open",
        havingValue = "true"
)
public class JongoAutoConfig {

    @Autowired
    private JongoAutoProperties jongoAutoProperties;

    @Bean
    @ConditionalOnMissingBean(
            name = {"mongoDatabaseFactory"}
    )
    public MongoDatabaseFactory mongoDatabaseFactory(){
        return new MongoDatabaseFactory();
    }

    @Bean
    @ConditionalOnMissingBean(name = "jongoTemplate")
    public JongoTemplate jongoTemplate(@Qualifier("jongo") Jongo jongo){

        return new JongoTemplate(jongo);
    }

    @Bean
    @ConditionalOnMissingBean(
            name = "jongo"
    )
    public Jongo jongo(){
        List<ServerAddress> serverAddresses = new ArrayList<>();
        ServerAddress serverAddress = new ServerAddress(this.jongoAutoProperties.getHost(), this.jongoAutoProperties.getPort());
        serverAddresses.add(serverAddress);
        serverAddress = new ServerAddress(this.jongoAutoProperties.getCluser(), this.jongoAutoProperties.getCport());
        serverAddresses.add(serverAddress);
        MongoCredential credential = MongoCredential.createCredential(this.jongoAutoProperties.getUsername(), this.jongoAutoProperties.getDatabase(), this.jongoAutoProperties.getPassword().toCharArray());
        MongoClientOptions.Builder build = new MongoClientOptions.Builder();
        build.minConnectionsPerHost(10);
        build.connectionsPerHost(200);   //与目标数据库能够建立的最大connection数量为50
        build.threadsAllowedToBlockForConnectionMultiplier(400); 
        build.maxWaitTime(1000*60*2);
        build.connectTimeout(1000*60*1);    //与数据库建立连接的timeout设置为1分钟
        MongoClientOptions myOptions = build.readPreference(ReadPreference.secondaryPreferred()).build();
//        MongoClientOptions myOptions = build.build();
        //数据库连接实例
        MongoClient mongoClient = new MongoClient(serverAddresses, credential, myOptions);
        DB mondb = mongoClient.getDB(this.jongoAutoProperties.getDatabase());
        return new Jongo(mondb);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
配置类里引入属性类JongoAutoProperties。里面使用@Bean分别实例化 MongoDatabaseFactory,JongoTemplate,Jongo。

1. MongoDatabaseFactory:自已定义的一个空类,为了防止SpringBoot自动装配autoconfigure里的MongoTemplate实例化。
2. JongoTemplate:自己封装的对业务的持久化对象,操作mongodb。为什么要封装这个对象,为了装逼。。。。
3. Jongo:第三方插件Jongo实例化对象。

JongoAutoProperties实例化有两种方式:
1.使用注解jongoAutoProperties。
2.使用构造方法:
public JongoAutoConfig(JongoAutoProperties jongoAutoProperties){
this.jongoAutoProperties = jongoAutoProperties;
}
使用构造方法时,需要注意,不能再写无参构造方法,因为启动的时候会默认使用无参构造去实例化类,如果没有的化才会使用有参构造

数据操作类JongoTemplate

package org.springframework.boot.autoconfigure.data.mongodb;

import org.jongo.Jongo;
import org.jongo.MongoCollection;

public class JongoTemplate {

    private Jongo jongo;
    public JongoTemplate(){}
    public JongoTemplate(Jongo jongo){
        this.jongo = jongo;
    }
    public MongoCollection getMongoCollection(String tableName){
        return jongo.getCollection(tableName);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
里面就封装类一个Jongo类。

MongoDatabaseFactory这个类是个空类

package org.springframework.data.mongodb;

public class MongoDatabaseFactory {
}
1
2
3
4
还有个最重要的文件spring.factories,因为SpringBoot在自动装配starter的时候扫描所有引入的jar包中的WEB-INF目录下的spring.factories这个文件。里面引入了我们自定义的Configuration。
我们可以参考SpringBoot封装好的starter。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.springframework.boot.autoconfigure.data.mongodb.JongoAutoConfig
1
按照目录创建好就行了。
org.springframework.boot.autoconfigure.EnableAutoConfiguration:这个类就是自动加载的配置类。springBoot会按照这个类的值去加载我们写的configuration。

到这就创建完了一个自定义starter。

3. 用到的注解
@ConfigurationProperties(prefix = “mongo”):装配application.properties中的属性,prefix设置前缀名,属性类的中的属性名字对应属性文件中的名字。
@Configuration :配置类注解,表明这个类是一个配置类。
@ConditionalOnClass({Jongo.class,JongoTemplate.class}) :配置类的加载条件,如果符合这个条件才加载,条件是某个类。这里是如果项目中引入的有Jongo,JongoTemplate这个类才去加载这个配置类
@EnableConfigurationProperties({JongoAutoProperties.class}):引入属性配置类。
@ConditionalOnProperty(
prefix = “mongo”,
value = “open”,
havingValue = “true”
):配置类的加载条件,如果符合条件才加载。条件是属性文件的配置值。
@ConditionalOnMissingBean(
name = {“mongoDatabaseFactory”}
):如果项目中还没有实例化这个类才去实例化,如果已经有就不会再去实例化,name指定名字。
别的就是一些常用的注解了。
这些注解在SpringBoot里封装的starter中都有体现,可以去了解下。

4.遇到的问题
1.Failed to execute goal io.spring.javaformat:spring-javaformat-maven-plugin:0.0.6:validate (default) on project spring-boot-starter-data-mongodb-jongo: Formatting violations found in the following files:
** /Users/lxxx/ld-springboot-mongo-jongo-starter/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDBPorperties.java **
Run spring-javaformat:apply to fix.

答:是因为这是自己写的starter,格式可能有些问题,解决方法上面也说了,在这个module下使用这个命令 mvn spring-javaformat:apply,得配置下maven环境。

2.在启动的时候JongoAutoConfig中JongoAutoProperties属性没有注入进来?
答:因为我多加了个无参构造方法,去掉就好了。

**3.项目启动成功,但是日志有报错:mongo cluster localhost:27017 connect timeout **
答:我在配置的时候配置了mongo的链接信息,没有配置过localhost:27017的配置,最后发现是SpringBoot的autoConfigure中配置了MongoAutoConfiguration,进源码看下:

看下这个加载的条件:项目中有MongoClient这个类,没有实例化org.springframework.data.mongodb.MongoDbFactory这个Bean对象。
那所以如果我们不想让SpringBoot自动加载这个配置,所以这两个条件得不能让它满足。MongoClient这个类我们肯定得用到,所以不能使用这个条件排除,所以要自己手动创建个org.springframework.data.mongodb.MongoDbFactory这个类,手动去实例化,
MongoAutoConfiguration检测到有org.springframework.data.mongodb.MongoDbFactory这个Bean对象才不会去实例话。
————————————————
版权声明:本文为CSDN博主「站在墙头上」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_19674263/article/details/107252975

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值