我眼中的CXF之Bus

本文详细介绍了CXF框架中的Bus组件,解释了Bus如何作为全局配置仓库,支持CXF内部扩展模块与核心模块之间的隔离及交互。通过具体实现如CXFBusImpl和ExtensionManagerBus,展示了Bus在配置管理、扩展模块加载等方面的作用。
CXF在设计之初就提供了对多种的Binding,Transport可插拔的配置,你只需要在你的Class Path中添加相关的Binding,Transport jars,CXF的Core就会自动加载这些模块,并调用相关接口创建对应的Binding和Transport。

想知道CXF是如何实现Plugable的灵活配置吗?想知道你如何获取你想要的各种CXF内部对象吗?想知道这些内部对象是如何注册和相互查找的吗?

在这里我们可以研究一下CXF Bus,看看Bus是如何帮助CXF内部扩展模块隔离其与Core模块之间的依赖关系的。 

 



说到Bus,它有很多的含义。Bus是我们每天乘坐的公车;也是现在炒得很火得概念ESB中的总线。在CXF中,我觉得Bus更像是一个全局配置仓库,你可以向Bus中存放任何你想存放的扩展对象,你也可以从Bus中获取你想要的扩展对象,这个Bus将CXF中的各扩展模块有机地组合在一起了。

我们现在从相关的代码中一窥究竟。

首先是Bus的接口

这里我们使用了Java5中的泛型,这样让我们的{get|set}Extension 接口简单明晰。
当然这样的接口也不是一开始就设计出来的。要知道在CXF之前的ObjectWeb Celtix版本中Bus的概念虽然没有怎么变,但是那时的接口很复杂,基本上你如果想要添加一个内部扩展对象,就得写上好几行得代码。

这里也许有人会问,Bus为什么要继承 InterceptorProvider呢?这和CXF架构中另一个有意思的部分Interceptor有关,大家可以参看我后面的文章。

而 run和shutdown 两个方法是从 CORBA 中的Bus延续过来的。
最后说一下 getId,这是由于一个JVM中可以存在多个Bus,我们可以通过Bus ID 来区分这些不同的Bus。


这里有几个和Bus创建相关的类

BusFactory
定义了创建Bus的基本方法,它是一个抽象类。这里需要注意的{get|set}DefaultBus这两个方法。了解JAXWS API的朋友可能会有这样的疑问,就是JAXWS API中没有Bus这一概念,如果CXF要实现JAXWS API
接口怎么引入Bus这一对象呢?CXF在实现JAXWS API过程中,通过调用BusFactory.getDefaultBus()来设置内部模块使用的Bus。getDefaultBus会检测静态变量defaultBus赋值情况来决定是否要创建新的Bus。 在这我们就引出了在CXF中如果要使用JAXWS API来创建服务的话,我们可以预先配置好Bus,然后通过调用BusFactory.setDefaultBus(),来设置CXF 在实现JAWS API中使用的Bus。

具体的例子大家可以参看AbstractJaxWsTest中的setUpBus()。在这里我们没有使用到HTTPTransport来进行UnitTest,而是使用一个简单LocalTransport来测试Client Server之间的通讯,其中奥妙大家可以慢慢体会。


CXFBusImpl
是Bus接口的具体实现。这里大家可以看看如何实现{get|set}Extension。


ExtensionManagerBus
是Bus接口的另一个实现。这个Bus通过读取Class Path 中的META-INF/bus-extensions.xml文件来获取扩展模块的信息。
在ExtensionManagerBus中的初始化代码中,你可以发现CXF core中所必须的Managers(Bus也算是一个Manager集中营)。其中有负责获取资源管理的ResourceManager,负责扩展模块管理的ExtensionManger,负责Bus生命周期管理的BusLifeCycleManager, 负责初始化Server端Transport的DestionationFactoryManager, 复杂初始化Client端Transport的ConduitInitiatorManager, 负责初始化Binding的BindingFactoryManager。

这里是SoapBinding bus-extension.xml的例子。


CXFBusFactory
继承了BusFactory,并通过ExtensionManagerBus来负责加载CXF的扩展模块。


SpringBusFactory
通过SpringApplicationContext来加载CXF扩展模块。SpringBusFactory是缺省的BusFactory。这里需要说明的是SpringBusFactory需要配合Spring来使用,如果Class Path中没有包含Spring jars,那CXF Core会使用CXFBusFactory来加载扩展模块。随着Spring的大量普及,相信大家会大量使用SpringBusFactory来创建Bus。
在SpringBusFactory中,初始化的Bus实例是CXFBusImpl。但是如果你搜索一下SpringBusFactory以及CXFBusImpl的代码,是不会发现类似与ExtensionManagerBus那样的初始化代码的。 这是为什么呢?

当当当, 这是就是Spring的强大Wire功能,相关的Manager初始化代码转变成为了CXF.xml。有意思吧!

<think>我们正在处理一个Java异常:java.lang.ClassNotFoundException:org.apache.cxf.bus.spring.SpringBus。这个异常表明在类路径中缺少了cxf-rt-bindings-soap模块(因为SpringBus类通常位于cxf-rt-core模块中,但根据错误信息,实际缺失的可能是cxf-rt-bindings-soap模块中的某个依赖,但这里明确提示的是SpringBus类)。不过,根据常见的CXF配置,SpringBus类是在cxf-rt-core模块中。解决方案步骤:1.检查Maven依赖(如果使用Maven)或Gradle依赖(如果使用Gradle)中是否包含了ApacheCXF的核心模块,特别是`cxf-rt-core`。2.确保版本一致性:所有CXF模块的版本应该相同,避免版本冲突。3.清理和重新构建项目:有时候构建工具没有正确下载或包含依赖,清理并重新构建可以解决。具体操作:对于Maven项目,在pom.xml中添加如下依赖(以3.4.0版本为例,但请根据实际情况选择版本,注意引用[1]中提到在IDEA环境中需要3.1.11或以上):```xml<dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-core</artifactId><version>3.4.0</version></dependency>```如果项目已经使用了Spring,还需要确保Spring相关依赖的版本与CXF兼容。另外,引用[3]提到了一个类似的异常(虽然类名不同),这也提示我们可能是由于依赖缺失或版本不一致导致。如果问题仍然存在,检查是否因为项目构建时没有正确包含该jar包。在IDE中可以查看项目的依赖树,确认cxf-rt-core是否存在以及版本是否正确。如果使用的是非Maven/Gradle的项目,需要手动下载cxf-rt-core的jar包并添加到类路径中。注意:引用[1]中提到在jetty容器和IDEA环境下,cxf版本需要3.1.11或以上,所以请确保版本不低于3.1.11。如果以上步骤无法解决,考虑检查类加载器的问题,特别是在应用服务器中部署时,可能存在类加载器隔离的问题,尝试调整类加载策略。最后,重新启动应用。因此,总结解决方案如下:1.添加或更新cxf-rt-core依赖到合适版本(>=3.1.11)。2.确保所有CXF模块版本一致。3.清理和重新构建项目。4.检查类加载问题(特别是在应用服务器中)。如果用户提供了更多上下文(如构建工具、CXF版本等),可以进一步具体分析。相关问题:1.如何检查Maven项目的依赖树?2.在Tomcat中部署时遇到ClassNotFoundException如何解决?3.ApacheCXFSpring框架整合的基本步骤是什么?</think>### Java.lang.ClassNotFoundException: org.apache.cxf.bus.spring.SpringBus 解决方案 该异常表明您的项目缺少 Apache CXF 的核心依赖或存在依赖冲突。以下是系统化的解决步骤: #### 1. **添加缺失的 CXF 依赖** 在 Maven 的 `pom.xml` 中添加核心依赖(推荐使用 3.1.11+ 版本): ```xml <!-- 核心依赖 --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-core</artifactId> <version>3.4.0</version> <!-- 或 3.1.11+ --> </dependency> <!-- Spring 集成支持 --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http-jetty</artifactId> <version>3.4.0</version> </dependency> ``` 如果使用 Gradle: ```gradle implementation 'org.apache.cxf:cxf-rt-core:3.4.0' implementation 'org.apache.cxf:cxf-rt-transports-http-jetty:3.4.0' ``` #### 2. **检查依赖冲突** - **执行依赖树分析**: ```bash mvn dependency:tree | grep cxf # Maven gradle dependencies --configuration runtimeClasspath # Gradle ``` - 若存在多个 CXF 版本,通过 `<exclusions>` 排除旧版本: ```xml <dependency> <groupId>com.example</groupId> <artifactId>problematic-lib</artifactId> <exclusions> <exclusion> <groupId>org.apache.cxf</groupId> <artifactId>cxf-core</artifactId> </exclusion> </exclusions> </dependency> ``` #### 3. **验证 Spring 配置** 确保 `spring-cxf.xml` 正确声明总线([^2]): ```xml <!-- 关键配置:显式声明 SpringBus --> <bean id="cxf" class="org.apache.cxf.bus.spring.SpringBus" destroy-method="shutdown"/> <jaxws:endpoint id="DemoService" implementor="#DemoServiceBean" address="/DemoService" bus="#cxf"/> <!-- 关联总线 --> ``` #### 4. **清理并重建项目** ```bash mvn clean install -U # -U 强制更新依赖 ``` 或清除 IDE 缓存: - **IntelliJ IDEA**:`File > Invalidate Caches / Restart` - **Eclipse**:右键项目 > `Maven > Update Project` #### 5. **容器部署注意事项** - **Jetty 容器**:必须使用 CXF 3.1.11+ 版本([^1]) - **Tomcat**:确保 `cxf-rt-transports-http` 依赖存在 - **War 包**:检查 `WEB-INF/lib` 是否包含 CXF JAR 文件 > **根本原因分析**: > 此异常通常由以下情况触发: > 1. 项目未包含 `cxf-rt-core` 或 `cxf-spring-boot-starter-jaxws`(Spring Boot) > 2. 依赖冲突导致类加载器无法定位 `SpringBus.class` > 3. Jetty 容器与旧版 CXF 的兼容性问题([^1]) > 4. 构建工具未正确拉取依赖(需 `-U` 强制更新) ### 相关问题 1. 如何解决 CXF 与其他框架(如 Spring Boot)的依赖冲突? 2. CXF 在 Jetty 容器中部署时有哪些特殊配置要求? 3. 如何通过日志诊断 CXF 的类加载失败问题? 4. CXF 3.x 和 2.x 版本在 Spring 集成中有哪些不兼容变更? [^1]: 引用自 CXF 与 Jetty 容器的版本兼容性说明 [^2]: 参考 Spring 整合 CXF 的端点配置规范 [^3]: 涉及 CXF 扩展机制加载失败的通用解决方案
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值