You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Java类动态实现不同包路径的WebResourceTransformerFactory接口?

Confluence 8-9版本WebResourceTransformerFactory兼容方案

首先明确:Java反射无法让一个类在运行时动态实现不同的接口。类的接口实现信息是编译期写入字节码的,运行时无法修改已加载类的继承/实现结构,所以靠反射直接实现动态接口适配不可行。

下面是两种可行的兼容方案,基于隔离接口实现+动态加载的思路:

方案一:适配器模式+多实现类分离

把业务逻辑和接口实现解耦,写一个通用的逻辑类,再分别为新旧接口写适配实现类,通过插件配置根据Confluence版本动态加载对应类。

步骤1:提取通用业务逻辑

将原本Transformer里的核心逻辑抽离成独立类,不依赖任何版本的接口:

// 通用转换逻辑,与Confluence版本无关
public class TransformerCore {
    // 这里放原本的业务代码
    public String processContent(String content) {
        // Do something...
        return transformedContent;
    }
}

步骤2:分别实现新旧接口

旧版本(Confluence 8)适配类

import com.atlassian.plugin.webresource.transformer.WebResourceTransformer;
import com.atlassian.plugin.webresource.transformer.WebResourceTransformerFactory;
import java.util.Map;
import java.io.Reader;
import java.io.StringReader;

public class OldTransformerAdapter implements WebResourceTransformerFactory {
    private final TransformerCore core = new TransformerCore();

    @Override
    public WebResourceTransformer createTransformer(Map<String, String> params) {
        return (reader, context) -> {
            // 读取输入内容
            String content = readReaderToString(reader);
            // 调用核心逻辑处理
            String processed = core.processContent(content);
            // 返回处理后的结果
            return new StringReader(processed);
        };
    }

    // 工具方法:将Reader转为String
    private String readReaderToString(Reader reader) {
        // 实现读取逻辑...
    }
}

新版本(Confluence 9+)适配类

import com.atlassian.webresource.spi.transformer.WebResourceTransformer;
import com.atlassian.webresource.spi.transformer.WebResourceTransformerFactory;
import java.util.Map;
import java.io.Reader;
import java.io.StringReader;

public class NewTransformerAdapter implements WebResourceTransformerFactory {
    private final TransformerCore core = new TransformerCore();

    @Override
    public WebResourceTransformer createTransformer(Map<String, String> params) {
        return input -> {
            String content = readReaderToString(input);
            String processed = core.processContent(content);
            return new StringReader(processed);
        };
    }

    private String readReaderToString(Reader reader) {
        // 同旧版本的工具方法实现
    }
}

步骤3:插件配置动态加载

在atlassian-plugin.xml中,利用Confluence的版本条件配置加载对应的适配器:

<!-- 适配Confluence 8及以下版本 -->
<web-resource-transformer 
    key="my-transformer-old" 
    class="com.yourcompany.plugin.OldTransformerAdapter"
    condition="com.atlassian.confluence.version &lt; 9.0.0">
    <!-- 配置参数 -->
</web-resource-transformer>

<!-- 适配Confluence 9及以上版本 -->
<web-resource-transformer 
    key="my-transformer-new" 
    class="com.yourcompany.plugin.NewTransformerAdapter"
    condition="com.atlassian.confluence.version &gt;= 9.0.0">
    <!-- 配置参数 -->
</web-resource-transformer>

方案二:OSGi动态导入+动态代理(进阶)

如果两个版本的接口方法签名完全一致,可以通过OSGi动态导入包结合Java动态代理实现单类适配,但复杂度较高:

步骤1:pom.xml配置动态依赖

<dependency>
    <groupId>com.atlassian.confluence</groupId>
    <artifactId>confluence-web-resources</artifactId>
    <version>[8.0.0,10.0.0)</version>
    <scope>provided</scope>
</dependency>

<!-- 动态导入两个包路径 -->
<Import-Package>
    com.atlassian.plugin.webresource.transformer;resolution:=optional,
    com.atlassian.webresource.spi.transformer;resolution:=optional,
    *
</Import-Package>

步骤2:写动态代理生成类

import java.lang.reflect.Proxy;
import java.util.Map;
import java.io.Reader;
import java.io.StringReader;

public class TransformerProxyFactory {
    private static final TransformerCore CORE = new TransformerCore();

    public static Object createTransformerFactory() throws Exception {
        // 先尝试加载新版本接口
        Class<?> factoryInterface;
        try {
            factoryInterface = Class.forName("com.atlassian.webresource.spi.transformer.WebResourceTransformerFactory");
        } catch (ClassNotFoundException e) {
            // 加载失败则用旧版本接口
            factoryInterface = Class.forName("com.atlassian.plugin.webresource.transformer.WebResourceTransformerFactory");
        }

        // 生成动态代理
        return Proxy.newProxyInstance(
            factoryInterface.getClassLoader(),
            new Class[]{factoryInterface},
            (proxy, method, args) -> {
                if ("createTransformer".equals(method.getName())) {
                    Map<String, String> params = (Map<String, String>) args[0];
                    // 获取Transformer接口类型
                    Class<?> transformerInterface = Class.forName(
                        factoryInterface.getPackage().getName() + ".WebResourceTransformer"
                    );
                    // 生成Transformer的代理
                    return Proxy.newProxyInstance(
                        transformerInterface.getClassLoader(),
                        new Class[]{transformerInterface},
                        (transProxy, transMethod, transArgs) -> {
                            if ("transform".equals(transMethod.getName())) {
                                // 处理转换逻辑,调用核心类
                                Reader input = (Reader) transArgs[0];
                                String content = readReaderToString(input);
                                String processed = CORE.processContent(content);
                                return new StringReader(processed);
                            }
                            return transMethod.invoke(null, transArgs);
                        }
                    );
                }
                return method.invoke(null, args);
            }
        );
    }

    private static String readReaderToString(Reader reader) {
        // 实现读取逻辑...
    }
}

步骤3:插件配置加载代理

在atlassian-plugin.xml中配置工厂类,通过静态方法获取代理实例:

<web-resource-transformer 
    key="my-transformer" 
    class="com.yourcompany.plugin.TransformerProxyFactory"
    factory-method="createTransformerFactory">
    <!-- 配置参数 -->
</web-resource-transformer>

注意事项

  1. 依赖配置要使用版本范围,确保同时兼容8和9版本的Confluence依赖
  2. 测试时要分别在Confluence 8和9环境下验证功能,避免接口方法签名差异导致的问题
  3. 优先选择方案一,代码更直观,维护成本更低;方案二适合接口方法完全一致的场景,复杂度较高

内容的提问来源于stack exchange,提问作者Leon kong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 17:36:34