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。有意思吧!