手动构建starter组件

之前的帖子说过,使用依赖尽量使用starter相关的依赖。因为这些相关的依赖会根据配置文件配置相关的类。比如在Spring中整合使用redis。那么在快速开发中,推荐使用spring-boot-starter-data-redis依赖,它会根据配置文件默认配置好redisTemplate等相关类。
那么接下来介绍如何构建starter组件。
首先对于自定义的starter(第三方),官方推荐的命名是xx-spring-boot-starter,只有Spring官方的starter命名是spring-boot-starter-xxx。

首先来看依赖部分。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 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.apex</groupId>
    <artifactId>myservice-spring-boot-starter</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
		
        <!-- 自定义springboot的组件,必须引入此依赖作为入口 -->
        <!--这里有我们需要的注解,Spring会根据EnableAutoConfigurationImportSelector注入相关的类-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <version>2.3.0.RELEASE</version>
        </dependency>

        <!-- 读取配置文件时的自动提示功能 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <version>2.3.0.RELEASE</version>
            <optional>true</optional>
        </dependency>
   
    </dependencies>
	<!--非必须,由于我打包时idea建议我使用UTF-8编码-->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
</project>

这边编写个YmlProperties类,用来读取yml配置文件。

package com.apex.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * @author ZJX
 * @date 2022/2/20
 * @description
 */
 //获取配置文件(application.properties或者application.yml)中前缀为myservice的属性
@ConfigurationProperties(prefix = "myservice")
public class YmlProperties {
    private String url;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }
}

接下来编写Service层。

package com.apex.service;

import com.apex.config.YmlProperties;
import org.springframework.stereotype.Service;

/**
 * @author ZJX
 * @date 2022/2/20
 * @description
 */
public class YmlService {
    private YmlProperties ymlProperties;
    public YmlService(YmlProperties ymlProperties){
        this.ymlProperties = ymlProperties;
    }
    public String getUrl(){
        if(ymlProperties!=null){
            return ymlProperties.getUrl();
        }else{
            return null;
        }
    }
    public YmlProperties getYmlProperties() {
        return ymlProperties;
    }

    public void setYmlProperties(YmlProperties ymlProperties) {
        this.ymlProperties = ymlProperties;
    }
}

接下来编写自动配置的配置类。

package com.apex;

import com.apex.config.YmlProperties;
import org.springframework.beans.factory.annotation.Autowired;
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 com.apex.service.YmlService;

/**
 * @author ZJX
 * @date 2022/2/20
 * @description
 */
 //说明该类是个配置类
@Configuration
//说明自动读取配置文件的类
@EnableConfigurationProperties(YmlProperties.class)
//标注配置文件需要配置特定属性才生效,在此处是需要配置myservice.enabled=true才生效,matchIfMissing表明如果不配置,默认为true即不配置默认生效
@ConditionalOnProperty(prefix = "myservice",name = "enabled",matchIfMissing = true)
public class MyAutoConfiguration {
    @Autowired
    YmlProperties ymlProperties;
    @Bean
    public YmlService ymlService (){
        return new YmlService(ymlProperties);
    }

}

接下来是配置spring.factories文件(在resources下的META-INF下,没有改文件或者目录需要自己创建)。

#配置自动加载的类
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.apex.MyAutoConfiguration

上述配置是因为@SpringBootApplication包含了@EnableAutoConfiguration。
在这里插入图片描述

而@EnableAutoConfiguration里通过@Import导入了AutoConfigurationImportSelector。
在这里插入图片描述
找到其中selectImports方法,可以看到其调用了getAutoConfigurationEntry方法。
在这里插入图片描述
而在getAutoConfigurationEntry方法中,是通过getCandidateConfigurations获取配置信息。
在这里插入图片描述
可以看到该方法继续调用了loadFactoryNames方法,后面的断言信息也说明了,实际是获取META-INF/factories文件。但是我们可以继续从方法中查找具体的文件。
在这里插入图片描述
在loadFactoryNames方法中,如果当前类加载对象存在,在当前类加载包下的指定路径下去加载,如果不存在就在当前系统类加载路径去找。而对于FACTORIES_RESOURCE_LOCATION来说,其指向META-INF/spring,factories文件(即会扫描各个jar包下的META-INF/spring.factories)。

在这里插入图片描述
在这里插入图片描述
最后在其他模块中引入该组件。

       <dependencies>
           <dependency>
               <groupId>com.apex</groupId>
               <artifactId>myservice-spring-boot-starter</artifactId>
               <version>0.0.1-SNAPSHOT</version>
           </dependency>
       </dependencies>

Controller层

@Controller
public class FirstController {
	//自动注入
    @Autowired
    YmlService ymlService;
    @GetMapping("/hello")
     @ResponseBody
    public String sayHello(){
     return ymlService.getUrl();
 }

}

该模块的application.yml文件。

myservice:
  url: 123

测试
在这里插入图片描述
虽然项目成功运行了,但是有个问题,那就是idea会报找不到该bean。那是因为YmlService是配置在其他模块下的,idea能找到该类,但是不知道该类是否被Spring容器控制反转,但实际上是的。
在这里插入图片描述
为了消除该爆红,我们可以在自定义的starter模块下的spring.factories下添加该Service类。
在这里插入图片描述
这样子就能很明显地告诉“idea”,该YmlService类会被Spring自动扫描并注入到Spring容器中。然后爆红也消失了。
在这里插入图片描述
最后给大家看看我的项目结构。
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值