本文主要介绍在JBOSS EAP 6.1(或者JBOSS AS7)中模块是如何贯穿EJB实现的始终。全文分两部分,第一部分介绍最简单的Session bean的Annotation方式的实现,对Annotation的方式熟悉的朋友直接跳过第一节。有了第一节的铺垫,第二节引入生产中的一个实例,延续上一博文《认识模块的使用》的话题继续聊JBOSS做为模块申明式容器的这一特性在EJB实现中的完全贯彻。
JBOSS EAP(AS7)中默认的EJB是3.1版本遵循JSR318规范。EJB从3.0开始已经全面引入Annotation的概念,3.0以前的EJB需要在XML文件里面对Bean所做的配置都能通过标签的方式在代码中实现。同时,之前为了工厂模式而做的双接口Home和Remote已经被一个业务接口所取代。由于Entity Bean的概念已经从EJB中拿出放到了JPA规范中,所以这里只介绍Session Bean最基本的Annotation方式的实现,为后文提供知识基础。
Session Bean由两部分组成:一个业务接口和一个具体实现业务的JAVA类。
import javax.ejb.Remote; @Remote public interface HelloWorldBusiness { public String sayHello(); }
是一个普通的JAVA类
在类名的上方使用@Stateless或者@Stateful来指明这个Session Bean是否有状态。
(有无状态的区别请参看hippoppower原创的帖子:http://blog.csdn.net/hippoppower/article/details/4190006介绍的很详细。)import javax.ejb.Stateless; @Stateless(name="Hello/World") public class HelloWorldBean implements HelloWorldBusiness { private static final long serialVersionUID = -1257752919635702689L; public String sayHello(){ return "Hello World."; } }
这就是一个最最简单的EJB的实现,对于之前的JBOSS AS到此就可以运行了,但是JBOSS EAP 6.1(或者JBOSS AS7)还需要对EJB做配置,具体配制方法在下一个小节中做介绍。
【EJB学习内容小扩展】
下面列举一些常用的标签,学习完它们大部分的应用都够了。
@Stateless
@Remote
@Local
@LocalBean
@EJB
@Resource
@Inject
@Stateful
@Init
@PostConstruct
@PreDestroy
@PrePassivate
@PostActivate
@Remove
以上介绍的都是服务端EJB的代码,Client端在下一篇博文《让人又爱又恨的EJB3.1 JNDI》介绍JNDI的时候会有更深入的介绍。
回到模块的话题,模块的具体配置方法请参看《Oracle数据源的配置—认识模块的使用》中第2部分介绍。本节使用一个生产中的实例来说明模块在EJB实现的整个过程中是如何贯穿始终的。
import com.XX.ngoss.XXX.commonclass.XXXConfiguration; import com.XX.ngoss.XXX.commonclass.XXXConsts; import com.XX.ngoss.XXX.commonclass.XXXUtils; import com.XX.ngoss.XXX.logmanager.server.LogManagerBusiness; import com.XX.ngoss.XXX.logmanager.server.LogFileNameInfo; import com.XX.ngoss.XXX.logmanager.server.LogView; @Stateless(name="XXX/Log_Manager") @Remote(LogManagerBusiness.class) public class LogManagerSession implements LogManagerBusiness, Serializable{ …… }
<?xml version="1.0" encoding="UTF-8"?> <module xmlns="urn:jboss:module:1.1" name="com.xx.ngoss.xxx.commonClass"> <dependencies> <module name="javax.api"/> <module name="javax.transaction.api"/> <module name="org.jboss.remote-naming"/> <module name="org.jython"/> </dependencies> <resources> <resource-root path="CommonClass.jar"/> </resources> </module>其中<module>标签中的name属性将这个模块命名为com.xx.ngoss.xxx.commonClass,同时在<dependencies>标签中指明了commonClass这个模块所依赖的其他模块:
<?xml version="1.0" encoding="UTF-8"?> <module xmlns="urn:jboss:module:1.1" name="org.jython"> <dependencies> <module name="javax.api"/> </dependencies> <resources> <resource-root path="jython.jar"/> </resources> </module>
LogManageCommon也用同样的方式配置好。被配置为名叫com.xx.ngoss.xxx.commonClass的模块。
LogManger是实现EJB业务的地方,最终部署的时候会被放置到jboss-eap-6.1\standalone\deployments中部署。与之前的JBOSS AS不同之处在于:JBOSS EAP 6.1(AS7)中一个EJB项目对JBOSS模块的依赖需要指明在MANIFAST.MF文件中。LogManager/src/META-INF/MANIFEST.MF文件如下配置:
Manifest-Version: 1.0这样就指明了EJB Project对JBOSS EAP 6.1中配置好的模块com.xx.ngoss.xxx.commonClass,com.xx.ngoss.xxx.logManagerCommon和org.jboss.log4j.logmanager的依赖。才完成整个EJB在JBOSS中的配置工作。剥离业务实现,这个日志组件的配置包括以下三步:
系统自带包,第三方包,自定义包全都变为模块,模块与组建之间需要指明依赖关系,同时EJB项目也需要指明依赖关系到JBOSS EAP中的组件上。JBOSS EAP 6.1中组件的概念可谓是深入骨髓。
本文首先介绍了最简单的EJB 3.1的实现,随后引入一个实例类说明JBOSS模块是如何配置到EJB项目、用户制作的lib、第三方的lib、系统lib之间来清楚的指明依赖关系的。这种设计为JBOSS容器优化带来了可行性。也在JBOSS EAP 6.1的启动与重启速度中得到了充分的证明。
但从开发人员的角度出发,虽然开发环境中JBOSS的起降性能有很大提升,但是这种所有lib都需要配置为module的方式没有原来直接仍到lib中的方式容易实现,由于module可能被配置在$JBOSS_EAP$/modules目录下的任何一级目录下,有的或许系统里面已经有了,有的需要引入,引入到什么位置,都由开发人员自行决定。这样的自由度一方面给开发人员带来了额外的工作量,另一方面如果多个开发人员一起开发,不同的模块引入相同的包到了不同级别的目录下,从而引发冲突。
综上所述,模块申明式容器这一新特性,从性能的角度来看值得欣赏,但对于开发人员来说是利弊参半。