仅需四步,写一个 Spring Boot Starter

Java技术栈

共 5815字,需浏览 12分钟

 ·

2020-10-11 14:31

Java技术栈

www.javastack.cn

关注阅读更多优质文章


引言

只要你用 Spring boot,一定会用到各种 spring-boot-starter。其实写一个spring-boot-starter,仅需4步。

下面我们就写一个starter,它将实现,在日志中打印方法执行时间。

第一步 创建maven项目

在使用spring-boot-starter,会发现,有的项目名称是 XX-spring-boot-starter,有的是spring-boot-starter-XX,这个项目的名称有什么讲究呢?

从springboot官方文档摘录如下:

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.

从这段话可以看出spring-boot-starter命名的潜规则。

spring-boot-starter-XX是springboot官方的starter

XX-spring-boot-starter是第三方扩展的starter

打印方法执行时间的功能,需要用到aop,咱们的项目就叫做

aspectlog-spring-boot-starter吧。

项目的pom文件如下:

"1.0" encoding="UTF-8"?>
"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">
    4.0.0

    org.example
    aspectlog-spring-boot-starter
    1.0.2
    
        org.springframework.boot
        spring-boot-starter-parent
        2.1.15.RELEASE
    

    
    
        
            org.springframework.boot
            spring-boot-autoconfigure
        

        
            org.springframework.boot
            spring-boot-starter-aop
        

        
            org.springframework.boot
            spring-boot-configuration-processor
            true
        

    



关于spring-boot-configuration-processor的说明,引自springBoot官方文档:

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:


  org.springframework.boot
  spring-boot-autoconfigure-processor
  true

简单说就是 写starter时,在pom中配置 spring-boot-autoconfigure-processor,

在编译时会自动收集配置类的条件,写到一个 META-INF/spring-autoconfigure-metadata.properties中。

不熟悉 Spring Boot 基础的可以看下这个仓库:https://github.com/javastacks/spring-boot-best-practice

第二步写自动配置逻辑

各种condition

类型注解说明

Class Conditions

类条件注解

@ConditionalOnClass

当前classpath下

有指定类才加载

@ConditionalOnMissingClass

当前classpath下无指定类才加载


Bean Conditions

Bean条件注解

@ConditionalOnBean

当期容器内有

指定bean才加载

@ConditionalOnMissingBean

当期容器内无指定bean才加载


Property Conditions

环境变量条件

注解(含配置文件)

@ConditionalOnProperty

prefix  前缀

name 名称

havingValue

 用于匹配配置项值

matchIfMissing  

没找指定配置项时

的默认值

Resource Conditions 

资源条件注解

@ConditionalOnResource有指定资源才加载

Web Application Conditions

web条件注解

@ConditionalOnWebApplication是web才加载
@ConditionalOnNotWebApplication不是web才加载
SpEL Expression Conditions@ConditionalOnExpression符合SpEL 表达式才加载

本次我们就选用@ConditionalOnProperty。即配置文件中有aspectLog.enable=true,才加载我们的配置类。

不熟悉 Spring Boot 基础的可以看下这个仓库:https://github.com/javastacks/spring-boot-best-practice

下面开始写自动配置类

2.1.定义AspectLog注解,该注解用于标注需要打印执行时间的方法。

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:   用于控制定时任务的开启与关闭
 * 对应切面
 * creat_user: wenl
 * creat_time:  2018/11/10 18:45
 **/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface   AspectLog {
}

2.2定义配置文件对应类

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;
    }
}

2.3定义自动配置类

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 {
        //执行方法名称 
        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() {
        //保证事务等切面先执行
        return Integer.MAX_VALUE;
    }
}

配置类简要说明:

@ConditionalOnProperty(prefix = "aspectLog", name = "enable",havingValue = "true", matchIfMissing = true)

当配置文件有aspectLog.enable=true时开启,如果配置文件没有设置aspectLog.enable也开启。基础知识不熟悉的可以关注公众号Java技术栈回复boot获取一份完整教程。

第三步META-INF/spring.factories

META-INF/spring.factories是spring的工厂机制,在这个文件中定义的类,都会被自动加载。多个配置使用逗号分割,换行用\

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.shanyuan.autoconfiguration.aspectlog.AspectLogAutoConfiguration

第四步打包测试

这是我们最终的目录结构

在IDEA中,进行mvn intall

打包完成后,在其他项目中的pom中引入进行测试


作者:温安适
来源:my.oschina.net/floor/blog/4435699




关注Java技术栈看更多干货



戳原文,获取精选面试题!
浏览 23
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报