关于将SipServlet的SipFactory注入到JavaEE 6的Bean中的折腾

折腾了几天终于比较满意地(Least-intrusive,Most-portable)解决了这个问题,,学到了不少东西。特分享如下。

(先吐个槽:不知为何国内关于JavaEE 6的资料如此至少。这可是个Gavin King (Hibernate, Seam 的leader) 极力推荐的、已开始可以和Spring媲美的东西(尤其是CDI)。后续加一些这方面说法的链接。)

基本环境: Mobicents SipServlet 3.0.0-Snapshot, JBoss AS 7.13, JavaEE 6

需求:用JavaEE6技术重构一个基于Mobicents做的VOIP的项目,本文只分享用CDI和EJB3.1的注解实现依赖注入的经验。其他以后如有需要再叙。

问题:如何便捷地将多才多艺的SipFactory注入到普通的bean(CDI管理)中,或者EJB3.1的bean中?

尝试1:直接@Resource。

public class MySipServlet extends SipServlet {@Resource private SipFactory sipFactory;…}@Singletonpublic class MyBean {@Resource private SipFactory sipFactory;}

结果:在SipServlet(MySipServlet)中会成功注入。一般的bean中(MyBean)不能成功注入,时而有NPE。

分析:经过艰苦卓绝的调查取证,我认为我找到了部分原因… 按Mobicents官方的说法,SipFactory只有在SipServlet容器Context启动时才会构建,而SipServlet容器是随着第一个SipServlet的初始化启动的。(注意默认都是Lazy Loading的)。也就意味着有可能上面的MyBean(即便为Stateless)需要注入和使用SipFactory的时候,它还没有准备好!即便有所谓的三种获取方式(JNDI调用,mappedName,和@Resource),上面的问题还是解决不了。尤其是如果需要加上@Startup给一个@Singleton的时候,它实例化的时后SipFactory肯定没准备好。

尝试2:基于上面分析,只能放弃上面三种方式。接下来自然就想到监听SipServletContext的事件,等它初始化完成SipFactory肯定就可以用了。

public class SipServletFacade1 implements SipServletListener {private SipFactory sipFactory;}public class SipServletFacade2 extends SipServlet implements SipServletListener {private SipFactory sipFactory;}

结果:SipServletFacade1貌似很简单但是好像Mobicents实现的容器不接受(只有SipServlet才能作为SipServletListener?),所以失败。SipServletFacade2侵入性太强(SipServlet应该在展现层而不是到业务层),所以还是早早放弃吧!

分析:注意到此时我们有了Facade模式和Event/Listener的思想。我们想用POJO模式的Facade封装SipServlet容器的工具类SipFactory,一方面屏蔽它的依赖注入方式,另一方面还有别的Facade的好处:比如简化实用,封装异常等等。可惜,可惜,上面的方式行不通…

最终尝试:JavaEE 6 来了!javax.enterprise.event.* 救了我们!

分析:注意使用JavaEE 6的Event/@Observes大大简化监听者模式的实现而且注入性小。实现了低耦合。

public class MySipServlet extends SipServlet() {@Resource SipFactory sipFactory;@Inject private Event<MyEvent> myEventEmitter;…@Overridepublic void init() {myEventEmitter.fire(new MyEvent(sipFactory));}public class SipServletFacade {private SipFactory sipFactory;public void sipServletInit(@Observes MyEvent myEvent) {sipFactory = myEvent.getSipFactory();}}

本文出自 “我劝天公重抖擞” 博客,请务必保留此出处

片的时光如浮云般流过,我们的青春单薄的穿梭在蓝天之上。

关于将SipServlet的SipFactory注入到JavaEE 6的Bean中的折腾

相关文章:

你感兴趣的文章:

标签云: