最近看了一篇微信上的文章:是 【码农翻身】公众号的刘欣作者写的Java帝国之JMS的诞生。最近恰好关注到支付宝的开源分布式消息中间件–Metamorphosis(MetaQ)(现在这个项目改名为RocketMQ)非常想看一下源码,但我知道阿里的一般比较复杂,所以从简单的activeMQ开始,当然这个JMS标准产生过程看看更好。
http://mp.weixin.qq.com/s/3b66QhyPl9sEkCnbgedF2g
一、文章的内容简介:
简述一下:JMS就是java消息服务,用于不同中模块对象之间的信息交互。比如其中之一P2P,就是一个发送消息,一个接收消息,就结束了,常用在异步处理时,不需要立即由接收方返回结果时(当然异步转同步也是可以的,发送方如果wait(),线程等待结果时,比如DUBBO的同步调用);还有一个主题订阅模式,就是一个人发消息,所以订阅过的人都可以收到消息。
但是很多厂商已经设计并开发了不同的消息中间件,那么,如果要对不同的产品进行统一标准,要需要对模块接口进行编程,厂商只是实现具体的功能。而模块接口正如文章中村长说:“不要被纷繁的现象迷住了双眼, 要看透背后的本质, 做出适当的抽象才可以。”。最后只剩下了一些:工厂queueConnFactory、队列queue、连接connect、交互session、生产者producer、消费者consumer、消息msg这些基本的概念产生的接口对象。这样基本的JMS标准就有了。这些接口只是一个架构,真正的实现是不同提供商提供的。
众多产品上升到标准的过程中,如果兼顾这么多产品呢?文章中提到的是JNDI(Java命名和目录接口)技术。这个技术我们一般会在配置数据库的时候会用到,比如配置JNDI数据源。但一个技术产生一定是有原因的,如果知道了原因,就知道如何在恰当的时候使用,以及处理问题的时候想到。
二、JNDI的例子:
JNDI简单的说可以有一个配置文件,那么就可以按名字从库中找到相应的对象。例子也是网上找的。比如我希望传一个String的地址,返回一个URL对象(或者实现某接口的对象),可以这样。
1.一个配置文件。有一个name,用来根据名称找对象。有一个type,表示找到的对象是什么接口的对象。还有一个factory后面要实现的,用来产生所要的对象。最后有一个url就是factory所要的相关参数。
<?xml version='1.0' encoding='utf-8'?>
<Context>
<Resource name="test/url"
auth="Container"
type="java.net.URL"
factory="com.tomcat.jndi.MyURLFactory"
url="file:///c:/test.properties"/>
</Context>
2.生产所要的对象的类的代码。
public Object getObjectInstance(Object obj, Name name, Context nameCtx,Hashtable environment) throws Exception {
URL url = null;
Reference ref = (Reference) obj;
Enumeration<RefAddr> cfgAttrs = ref.getAll();//这个是取配置文件的所有属性。
while (cfgAttrs.hasMoreElements()) {//循环查看属性
RefAddr cfgAttr = cfgAttrs.nextElement();
String attrName = cfgAttr.getType();//属性的名称
String attrValue = (String) cfgAttr.getContent();//属性的内容
if ("url".equals(attrName)) {
url = new URL(attrValue);//如果找到url属性,就用这个地址产生一个URL对象。当然实际使用中,可以new出最后的对象,设置相关的属性。
}
}
return url;//最终返回产生的对象。
}
3.使用
Context ctxt = new InitialContext();
Context envCtxt = (Context) ctxt.lookup("java:comp/env/");
URL url = (URL) envCtxt.lookup("test/url");//配置中的对象的名字,找到需要的对象。
4. 例子很简单,我们常用的JNDI数据源也是这样,从中可以看出,jndi就是配置后,不用使用基于Class.forName("xxx")的方式来装载类了,把装载过程从硬编码中移到配置中,这样就可以动态整合不同的模块功能了。
在我之前做过的项目中,也有对接口编程的例子,看到过使用数据库记录相关接口的实现类,并有名称,到时按条件查到后用Class.forName,也是一种动态。
三、目前见的比较多的SPI(Service Provider Interface)机制
除了上面说过JDNI外,我在DUBBO中看到了很多使用SPI的地方,DUBBO就是微核心设计,所以关注与接口整合功能模块,而且spi用的很复杂,加载的不一定是实际类,而是动态代理类。
当产生接口框架后,厂商提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。
同样基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定。
简单的例子可以看:
http://singleant.iteye.com/blog/1497259
阿里的DUBBO中全部用的是SPI。
四、总结
从上面的jms标准到JNDI与SPI的机制可以看到,对于一个产品来说,模块之间的功能关联应该通过接口来实现,而模块内部不一定都要写在接口。而我们想设计一个产品的时候,通过也是抽象的概念,用接口分离出整合关系,这样的产品才是一个微核心,可插拔的产品,更具灵活性。模块之间是通过JNDI或者SPI机制产生具体的实现类。
平时写代码,通常照猫画虎,ACTION/SERVICE/DAO都写成interface与impl方式。通过上面的介绍,更能理解接口的好处以及通过接口整合模块功能的方式,在开发中也不一定都弄成接口与实现分离的方式吧。
如果要区分一下什么时候用JNDI,什么时候用SPI。不妨考虑一下熟悉的JNDI的数据源是不是可以用SPI来实现?而SPI的东西是不是可以用JNDI来实现呢?初步感觉JNDI多了配置文件,而且数据源中的很多内容是标准中定义的接口,比如datasource,connection,recordset等等,所以说这种方式已经深入到很多内部的协作了,文章开关讲的JMS用JDNI也是浸入到内部的类的协作了。而用SPI,很多时候只是对外的一个接口的实现,并不是很浸入到实现的模块内部的关系。至于其它的方面还需要以后体会...
五、预告
前阵了研究了一下Apache commons fileupload的源码,特别是处理文件上传时写的非常好,一边读取流,一边产生内部类的iterator对象,并按boundery分段把输入流写到不同的输出流。下次再写...
分享到:
相关推荐
Java Naming and Directory Interface (JNDI) 是Java平台提供的一种标准服务接口,用于在分布式环境中查找和管理资源。JNDI的主要目的是为了统一不同类型的命名和目录服务,使得开发者可以通过相同的API访问不同的...
JMS是Java平台上的一个标准接口,它定义了生产、存储和消费消息的一组API。消息中间件,如ActiveMQ、RabbitMQ或Apache Kafka,通过JMS提供服务,使得分布式系统中的组件可以相互通信,而无需直接依赖对方。Spring ...
JMS是一个Java API,定义了生产、消费、队列和主题的标准接口。消息生产者创建消息并将其发送到目的地(队列或主题),而消息消费者则从这些目的地接收消息。Spring JMS通过提供Template类简化了这个过程,它封装了...
在IT领域,`JNDI`(Java Naming and Directory Interface)是Java平台提供的一种标准接口,用于访问命名和目录服务。它允许应用程序查找和操作不同类型的网络资源,如数据源、EJB等。而`SSH`(Struts、Spring、...
JNDI(Java Naming and Directory Interface)是SUN公司提供的一种标准的Java命名系统接口,JNDI提供统一的客户端API,通过不同的访问提供者接口JNDI SPI的实现,由管理者将JNDI API映射为特定的命名服务和目录系统,...
本文档主要介绍Java Naming and Directory Interface (JNDI) Service Provider Interface (SPI)的相关概念和技术细节,旨在帮助开发者更好地理解并实现JNDI服务提供者接口的功能。 ##### 1.1 文档概述 本文档提供...
Java Naming and Directory Interface (JNDI) 是Java平台中用于访问和管理命名和目录服务的一组接口和类。它提供了一种标准的方式来查找和访问多种类型的资源,如数据源、对象服务、邮件服务器等。JNDI的核心理念是...
在Java世界中,JNDI(Java Naming and Directory Interface)是一种标准接口,它允许应用程序查找和绑定各种命名和目录服务。这个技术的核心理念是提供一个统一的接口来访问不同的资源,比如数据库连接、EJB...
10. **学习资料**:提供的文档,如`java的JNDI 技术介绍及应用.docx`和`jndi step by step - aurawing - 博客园.pdf`,可能包含JNDI的详细教程和实践指南。`Untitled-1.html`可能是另一个相关文档,虽然其确切内容...
例如,在 JMS、JMail、JDBC、EJB 等技术中广泛使用了 JNDI 技术。 #### 二、JNDI 的诞生背景 随着分布式应用的发展,远程访问对象的需求日益增加。虽然传统的 Socket 编程可以实现远程通信,但在实际应用中存在...
- **在Java技术中的角色**:JNDI在EJB、JDBC、JMS等技术中扮演关键角色,比如在EJB中用于查找和绑定EJB组件。 通过JNDI,开发者可以方便地在分布式环境中查找和使用资源,如EJB组件、数据库连接、消息队列等,而...
* JNDI SPI(Service Provider Interface)提供了一个标准的接口,以便应用程序可以访问不同的目录服务。 JNDI 在 Java 平台中的地位: * JNDI 被包含在 Java 2 SDK 1.3 及其更新版本中。 * JNDI 还可以用作 JDK ...
JTA提供了一种标准的Java编程接口,用于访问事务服务,这些事务服务允许应用程序执行分布式事务处理——跨多个资源管理器(如数据库、消息服务等)的事务处理。在JTA中,事务由事务管理器进行协调,它控制事务的提交...
**JNDI相关书籍** 对于深入理解和应用JNDI技术至关重要。这些书籍通常会涵盖以下主题: 1. **JNDI基础**:介绍JNDI的基本概念,包括命名空间、上下文、查找和绑定操作。 2. **JNDI实现**:讲解不同类型的JNDI提供商...
Java 分布式处理技术 RMI,JNDI Java 分布式处理技术是指在 Java 平台上实现分布式计算和对象之间的交互的技术。其中,RMI(Remote Method Invocation)是 Java 分布式处理技术的核心组件之一。RMI 允许在不同的 ...
**JNDI(Java Naming and Directory Interface)**是Java平台中的一个重要组件,它提供了一种标准的方法来查找和访问各种命名和目录服务。这个小项目是针对初学者设计的,旨在帮助他们理解JNDI的基本概念和用法。 ...