手写可插拔的日志模块,感受springboot的自动装配与spring SPI

举报
developer_Li 发表于 2025/07/19 18:36:51 2025/07/19
【摘要】 目标让不同日志实现(比如 Logback、Log4j2)像插件一样自动加载具体实现定义日志接口(服务提供者)public interface LogService { void log(String message);}实现两个日志类(模拟不同日志框架)同时结合 @ConditionalOnProperty 选择实现类(如果在下面的自动装配类的构造方法上已经有了@Conditional...

目标

让不同日志实现(比如 Logback、Log4j2)像插件一样自动加载

具体实现

  1. 定义日志接口(服务提供者)

    public interface LogService {
        void log(String message);
    }
  2. 实现两个日志类(模拟不同日志框架)同时结合 @ConditionalOnProperty 选择实现类(如果在下面的自动装配类的构造方法上已经有了

    @ConditionalOnProperty,则这里就不需要了)

    @Service
    @ConditionalOnProperty(name = "logging.plugin", havingValue = "logback")
    public class LogbackService implements LogService {
        public void log(String msg) {
            System.out.println("[Logback] " + msg);
        }
    }
    
    @Service
    @ConditionalOnProperty(name = "logging.plugin", havingValue = "log4j2")
    public class Log4jService implements LogService {
        public void log(String msg) {
            System.out.println("[Log4j2] " + msg);
        }
    }
    
  3. 自定义 Starter 模块,结构如下:

    logging-starter/
    ├── META-INF/spring.factories
    ├── src/main/java/com/example/logging/
    │   ├── LogService.java
    │   ├── LogbackService.java
    │   └── LogAutoConfiguration.java
    
  4. 配置自动装配类:

    @Configuration
    public class LogAutoConfiguration {
    
        @Bean
        @ConditionalOnProperty(name = "logging.plugin", havingValue = "logback")
        public LogService logback() {
            return new LogbackService();
        }
    
        @Bean
        @ConditionalOnProperty(name = "logging.plugin", havingValue = "log4j2")
        public LogService log4j2() {
            return new Log4jService();
        }
    }
    
  5. spring.factories 文件中注册:

    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    com.example.logging.LogAutoConfiguration
    
  6. 提供一个 SPI 插件接口:

    public interface LogPluginProvider {
        LogService getLogService();
    }
    
  7. 第三方只需实现 LogPluginProvider,并在 META-INF/services 中注册,就能注入自己的日志框架,你通过 ServiceLoader 把它加载进来:(这一段逻辑可以加到自动装配类的构造方法中)

    ServiceLoader<LogPluginProvider> loader = ServiceLoader.load(LogPluginProvider.class);
    for (LogPluginProvider provider : loader) {
        LogService service = provider.getLogService();
        service.log("来自插件的日志");
    }
    
  8. 支持配置文件动态启用某个日志实现,在 application.yml 中添加:

    logging.plugin: logback
    
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。