提高项目可扩展性的java spi机制运用-自定义日志框架

1. 理论参考

2. 案例提供一个简单的日志框架myslf4j

在这里插入图片描述

  • ①定义核心接口
public interface MySlf4j {

    void log(String msg);

}
  • ②定义一个默认实现(有些框架不一定给默认实现,如果用户也引入厂商的实现就报错,这里还是给个默认实现比较好)
public class MySlf4jDefaultImpl implements MySlf4j {
    @Override
    public void log(String msg) {
        System.out.println("MySlf4j的默认实现MySlf4jDefaultImpl:"+msg);
    }
}
  • ③resources/META-INF/services/下载配置这个实现,ServiceLoader#load()方法就会加载里面的实现。如上图,文件名为接口名 ,内容为实现类全路径,加载时会通过放射实例化
  • ④再写一个类来获取MySlf4j的实现进行,以便使用MySlf4j的现在
public class LogFactory {
    public static MySlf4j getFirstLogger(){
        List<MySlf4j> allImpls = getProviders();// 如果引入2个厂商实现,且在maven中优先引入B实现,则这里加载到的是B的实现(maven就近原则也许就是这么玩的)
        return allImpls.get(0);
    };

    public static MySlf4j getLastLogger(){
        List<MySlf4j> allImpls = getProviders();
        return allImpls.get(allImpls.size()-1);//要最后一个加载的
    }
    public static List<MySlf4j> getAllLogger(){ //默认及所有厂商实现都要
        return getProviders();
    }
    private static List<MySlf4j> getProviders() {
        ServiceLoader<MySlf4j> providers = ServiceLoader.load(MySlf4j.class);
        Iterator<MySlf4j> it = providers.iterator();
        List<MySlf4j> allImpls = new ArrayList<>();
        while (it.hasNext()) {
            allImpls.add(it.next());
        }
        return allImpls;
    }

    ;
}

3.测试框架

就改项目mvn install到本地maven仓库,再在业务项目引入my-slf4j进行日志打印

<dependency>
   <groupId>com.xxx</groupId>
    <artifactId>my-slf4j</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

测试my-slf4j
在这里插入图片描述

4.厂商jwolf实现

  • ①厂商实现需要先引入my-slf4j定义的接口
<dependency>
   <groupId>com.xxx</groupId>
    <artifactId>my-slf4j</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
  • ②自己实现MySlf4j接口
public class JwolfMySlf4j implements MySlf4j {
    @Override
    public void log(String msg) {
        System.out.println("Jwolf厂商实现JwolfMySlf4j:"+msg);
    }
}
  • ③注册实现,注意文件名仍然为com.xx.MySlf4j 实现写Jwolf自己的实现的类全路径
    在这里插入图片描述

5.业务项目同时引入my-slf4j,及其厂商实现jwolfmyslf4j,且my-slf4j先引入,则优先加载的是my-slf4j

在这里插入图片描述

在这里插入图片描述

6.交换my-slf4j,及其厂商实现jwolfmyslf4j引入顺序,providers加载顺序也变了

在这里插入图片描述
在这里插入图片描述
总结

  • 本案例利用spi机制实现了类似原生slf4j的日志框架,my-slf4j具有可扩展性,具体厂商实现具有可插拔性
  • 多个实现时的加载顺序有点类似maven的就近原则,最短路径原则
  • 使用该机制可实现市面上有些框架类似的plugin就可以利用spi实现,插件制造者实现统一的接口,并将包放入plugin下吗,serviceload就可加载。只是这些plugin在项目外,需要配置外置jar包加载路径
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本人有多年java项目开发经验,在大大小小java项目中,总结写了这个通用日志信息记录开发包,愿结识各路好友。 压缩包,包涵使用实例,使用中如有疑问,可以QQ:120849208 以下是配置文件内容: #日志文件所在目录,不指定则为当前目录。特别注意,在windows的目录分隔符为"\\",例如 c:\\logs(重启后生效) logFileDirectory=./logs #日志文件主文件名(重启后生效) logFileMainName=ex #日志文件扩展名(重启后生效) logFileExtendedName=log #日志文件生成周期,分别为 0:不周期性产生文件;1:分钟;2:每小时;3:每天;4:每星期;5:每月;6:每年(重启后生效) logFileCycle=5 #当logFileCycle为1时有效,指定分钟数(重启后生效) logCycleMinutes=15 #要求跟踪级别,分别为 0:总是;1:错误;2:警告;3:普通(立即生效) logTrackLevel=3 #是否在日志记录前加日期时间字符串,取值0或1(立即生效) isAddDateTimeStringToHead=1 #当isAddDateTimeStringToHead为1时有效,表示时间串的格式,必须为java认识的时间格式;特别的,如果为“UNIX_TIMESTAMP”则时间以unix时间戳表示(立即生效) logHeadDateTimeStringFormat=yyyy-MM-dd HH:mm:ss #当isAddDateTimeStringToHead为1时有效,表示时间串和日志信息之间的间隔符,特别的,如果为空格请用双引号,例如:splitChar=" "(立即生效) splitChar=" " #是否在日志信息之后加换行符,取值0或1(立即生效) isAddNewLineToEnd=1 #是否在日志信息头加等级信息,取值0或1(立即生效) isAddLevelStringToHead=0 #日志信息是否输出到屏幕,取值0或1(立即生效) isLogTrackToScreen=1 #立即生效,日志信息是否输出到文件,取值0或1(立即生效) isLogTrackToFile=1

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值