手写一个starter

什么是Starter?Starter其实就是我们经常在maven中的导入的各种模块,自定义Starter可以快速的满足开发的需求,并且可以重复使用无需粘贴代码,直接从maven仓库中导入即可。那么我们如何自定义一个Starter呢?这里我们以自动记录接口请求时间为例(自定义Starter的知识点只需看主要部分即可):

starter命令规则

这段话的大概意思就是,麻烦大家遵守这个命名规范:

Srping官方命名格式为:spring-boot-starter-{name}

非Spring官方建议命名格式:{name}-spring-boot-starter

项目演示

新建工程

首先新建一个maven 工程,名称定义为demo-spring-boot-starter
在这里插入图片描述

在这里插入图片描述

Pom引入依赖
<?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>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.llc</groupId>
    <artifactId>demo-spring-boot-starter</artifactId>
    <version>1.0.0</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>


    <dependencies>
        <!-- 提供了自动装配功能-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <!-- 在编译时会自动收集配置类的条件,写到一个META-INF/spring-autoconfigure-metadata.json中-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
        </dependency>
        <!--记录日志会用到切面,所以需要引入-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <version>2.2.1</version>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <goals>
                            <goal>jar-no-fork</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

spring-boot-autoconfigure :提供自动化装配功能,是为了Spring Boot 应用在各个模块提供自动化配置的作用;即加入对应 pom,就会有对应配置其作用;所以我们想要自动装配功能,就需要引入这个依赖。

spring-boot-configuration-processor:将自定义的配置类生成配置元数据,所以在引用自定义STARTER的工程的YML文件中,给自定义配置初始化时,会有属性名的提示;确保在使用@ConfigurationProperties注解时,可以优雅的读取配置信息,引入该依赖后,IDEA不会出现“spring boot configuration annotation processor not configured”的错误;编译之后会在META-INF 下生成一个spring-configuration-metadata.json 文件,大概内容就是定义的配置的元数据;

spring-boot-starter-aop :记录日志,我们用到切面的功能,所以需要引入。

定义属性配置
package com.llc.config;


import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;

@Data
@ConfigurationProperties(prefix = "llc")
public class LogProperties {


    /**
     * 是否开启日志
     */
    private boolean enable;


    /**
     * 平台:不同服务使用的区分,默认取 spring.application.name
     */
    @Value("${spring.application.name:#{null}}")
    private String platform;


}

@ConfigurationProperties:该注解和@Value 注解作用类似,用于获取配置文件中属性定义并绑定到Java Bean 或者属性中;换句话来说就是将配置文件中的配置封装到JAVA 实体对象,方便使用和管理。

这边我们定义两个属性,一个是是否开启日志的开关,一个是标识平台的名称。

定义自动配置类
package com.llc.config;

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 *
 * @author llc
 * @date 2023/11/14
 */
@Configuration
@ComponentScan("com.llc")
@ConditionalOnProperty(prefix = "llc",name = "enable",havingValue = "true",matchIfMissing = false)
@EnableConfigurationProperties({LogProperties.class})
public class LogAutoConfiguration {

}

这个类最关键了,它是整个starter 最重要的类,它就是将配置自动装载进spring-boot的。

配置EnableAutoConfiguration

在resources/META-INF/ 目录新建spring.factories 文件,配置内容如下;

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.llc.config.LogAutoConfiguration
业务实现
package com.llc.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestLog {
}

定义切面执行逻辑,这边就简单的打印一下配置文件的属性值+目标执行方法+耗时。

package com.llc.aop;

import com.llc.annotation.RequestLog;
import com.llc.config.LogProperties;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;


@Aspect
@Component
@Slf4j
@AllArgsConstructor
public class LogAspectjProcess {


    LogProperties logProperties;


    /**
     * 定义切点
     */
    @Pointcut("@annotation(com.llc.annotation.RequestLog)")
    public void pointCut() {
    }


    /**
     * 环绕通知
     *
     * @param thisJoinPoint
     * @param requestLog
     * @return Object
     */
    @Around("pointCut() && @annotation(requestLog)")
    public Object around(ProceedingJoinPoint thisJoinPoint, RequestLog requestLog) {


        //执行方法名称
        String taskName = thisJoinPoint.getSignature()
                .toString().substring(
                        thisJoinPoint.getSignature()
                                .toString().indexOf(" "),
                        thisJoinPoint.getSignature().toString().indexOf("("));
        taskName = taskName.trim();
        long time = System.currentTimeMillis();
        Object result = null;
        try {
            result = thisJoinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        log.info("{} -- method:{} run :{} ms", logProperties.getPlatform(), taskName,
                (System.currentTimeMillis() - time));
        return result;


    }


}

整体项目结构就是这样子

在这里插入图片描述

starter这样就完成了
在这里插入图片描述
上传到maven仓库中。

项目中使用

引入pom

 <dependency>
            <groupId>com.llc</groupId>
            <artifactId>demo-spring-boot-starter</artifactId>
            <version>1.0.0</version>
 </dependency>

yml配置

在这里插入图片描述

测试
在这里插入图片描述

http://localhost:8080/test

在这里插入图片描述
转载地址:https://zhuanlan.zhihu.com/p/596170608

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱上编程2705

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值