xml文件的动态化配置,导入

1 背景

由于项目需要,得在通用框架中引入sdk,切面实现数据上报相关的功能,为最小化修改范围和影响,避免其他未用到改sdk的服务的启动、加载时间,实现了xml文件的动态化导入,满足条件才会加载。

服务是springboot项目,rpc接口。

2 实现

基于configuration、conditional,import,importResource注解,和thrift的interceptor实现。

  1. 实现Condition接口的matches(ConditionContext context, AnnotatedTypeMetadata metadata)方法,写一个条件类(conditional注解),满足该类的条件时才会执行xml的加载操作。
  2. 实现一个子配置类,importResource导入xml文件和相关bean
  3. 在主配置类Import子配置类,启动类import主配置类实现xml的动态带入和interceptor的动态注入

示例

java 复制代码
// 条件类
public class XXEnabledCondition implements Condition {
    private static final Logger LOGGER = LoggerFactory.getLogger(XXEnabledCondition.class);
    
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        try {
            boolean isEnabled = XXDebugConfig.isEnabled();
            LOGGER.info("XX Debug Condition Check: XX.debug.enable={}, condition={}", isEnabled, isEnabled);
            return isEnabled;
        } catch (Exception e) {
            LOGGER.warn("Failed to check XX Debug condition, XX Debug disabled", e);
            return false;
        }
    }
}
//子配置类
@Configuration
@Conditional(XXEnabledCondition.class)
@ImportResource(locations = {"classpath:XX-client.xml"})
public class XXClientConfiguration {
    private static final Logger LOGGER = LoggerFactory.getLogger(XXClientConfiguration.class);

    public XXClientConfiguration() {
        LOGGER.info("XXClientConfiguration initialized - XX Debug is enabled");
    }
}
//主配置类和子配置类一样的做法,就不贴了

3 扩展知识

conditional注解&condition接口

conditional注解是spring4.0引入的条件化bean注册注解,底层依赖Condition接口的match方法。

应用场景:

  • 根据文件 或 配置 差异定制化注册bean
  • 根据某个类是否存在判断是否注册bean

springboot基于conditional注解加了派生类:

  • @ConditionalOnProperty

  • @ConditionalOnClass

  • @ConditionalOnMissingBean

  • 等20+条件注解

注意事项

  1. 条件判断时机:发生在Bean定义阶段,早于Bean实例化

  2. 优先级问题@Conditional的优先级高于@Profile

  3. 避免循环依赖:条件判断中不要直接获取Bean实例

  4. 适用范围: 可以加在类 或 方法

  5. 调试技巧 :通过-Ddebug查看条件评估报告(Spring Boot)

高级用法见:https://blog.csdn.net/qq_62775328/article/details/145433841?ops_request_misc=elastic_search_misc&request_id=5bea71484c011adc0a57cdba124617f8&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-145433841-null-null.142^v102^pc_search_result_base8&utm_term=conditional%E6%B3%A8%E8%A7%A3&spm=1018.2226.3001.4187

configuration注解

核心作用:将 java类 转为spring配置类,保存在spring容器中,被统一管理。

高级用法:

  1. 模块化配置:@configuration + @import注解,不同模块分开配置。
  2. 条件化加载:利用@condition注解或springboot的@ConditionalOnProperty等注解
  3. 环境特定配置:结合@profile注解

注解参数:

  • proxyBeanMethods:bean代理方式,默认true,通过CGLIB代理,耗时更长!但确保单例(如通过serviceA()方法注入,多次调用该方法返回同个bean);false 耗时更短,但不保证单例。

  • value:配置bean名字

spring容器加载流程

java 复制代码
┌─────────────────┐
│  Spring 容器启动  │
└─────────┬───────┘
          │
          ▼
┌─────────────────┐
│ 扫描 @Configuration 类 │
└─────────┬───────┘
          │
          ▼
┌─────────────────┐
│  创建配置类实例   │
└─────────┬───────┘
          │
          ▼
┌─────────────────┐
│   处理 @Bean 方法  │
└─────────┬───────┘
          │
          ▼
┌─────────────────┐
│ proxyBeanMethods? │
└─────┬───────┬───┘
      │       │
      ▼       ▼
┌─────────┐ ┌─────────┐
│创建CGLIB│ │直接调用 │
│   代理   │ │  方法   │
└─────┬───┘ └─────┬───┘
      │           │
      └─────┬─────┘
            │
            ▼
┌─────────────────┐
│  注册 Bean 到容器 │
└─────────┬───────┘
          │
          ▼
┌─────────────────┐
│   处理依赖注入   │
└─────────┬───────┘
          │
          ▼
┌─────────────────┐
│    完成配置      │
└─────────────────┘

import注解

**作用:**把其他类拉进当前spring容器,解决bean扫不到的问题(如不在扫描路径下的第三方jar包的类,没加component等注解的普通类,想动态决定要不要引入的类)。

使用场景:

  1. 把普通类引入:这时类会被注入,spring会自动加载里面的各bean
  2. 导入配置类:把配置类里的bean导入
导入 "ImportSelector 接口实现类"------ 动态导入(高级用法)。
  1. 实现 ImportSelector 接口,在 selectImports 方法里返回要导入的类名数组
  2. 在配置类上 @Import 这个实现类

其实在被import的子配置上加condition注解也可实现3

importResource注解

**作用:**将xml配置加载到基于 Java 的到配置中,进而进入spring上下文中

@ImportResource支持各种 XML 配置文件的位置,包括:

  • 类路径classpath:beans.xml
  • 文件系统file:/path/to/beans.xml
  • URLhttp://example.com/beans.xml
相关推荐
暮色妖娆丶2 小时前
SpringBoot 启动流程源码分析 ~ 它其实不复杂
spring boot·后端·spring
Coder_Boy_2 小时前
Deeplearning4j+ Spring Boot 电商用户复购预测案例中相关概念
java·人工智能·spring boot·后端·spring
雨中飘荡的记忆2 小时前
Spring Batch实战
java·spring
callJJ3 小时前
Spring AI 文本聊天模型完全指南:ChatModel 与 ChatClient
java·大数据·人工智能·spring·spring ai·聊天模型
wxin_VXbishe3 小时前
C#(asp.net)学员竞赛信息管理系统-计算机毕业设计源码28790
java·vue.js·spring boot·spring·django·c#·php
无心水4 小时前
分布式定时任务与SELECT FOR UPDATE:从致命陷阱到优雅解决方案(实战案例+架构演进)
服务器·人工智能·分布式·后端·spring·架构·wpf
Coder_Boy_4 小时前
Deeplearning4j+ Spring Boot 电商用户复购预测案例
java·人工智能·spring boot·后端·spring
闻哥4 小时前
Kafka高吞吐量核心揭秘:四大技术架构深度解析
java·jvm·面试·kafka·rabbitmq·springboot
千寻技术帮5 小时前
10327_基于SpringBoot的视频剪辑咨询网站
mysql·源码·springboot·代码·视频咨询
历程里程碑5 小时前
普通数组----轮转数组
java·数据结构·c++·算法·spring·leetcode·eclipse