Eclipse下使用J2EE客户端和Hibernate

Eclipse加载各个插件时,每个插件采用单独的线程,因此插件之间的同名对象是不同的,不能进行类型转换。这样的话,如果某些插件需要采用别的方式加载某些类库,将不能与Eclipse本身加载的类进行转换。此问题突出表现在J2EE客户端接口上。

    为什么不同线程加载的同名类文件在JVM内部是不同的?请参考《深入Java虚拟机》一书,对其有比较详细的描述。

    eclipse中,不同的插件由eclipse生成一个线程,由此线程负责相应插件需要的类文件的加载。这样的好处是避免了不同插件之间可能存在的类文件的冲突(例如版本不一致引起的问题),但是也带来了不同的插件之间加载的类不同的问题(例如假设两个插件都加载了log4j,则两个插件之间的log4j对于JVM来说是两个不同的对象)。

    在采用J2EE结构时,通常提供给J2EE客户端各种远程接口。通过JNDI查找远程Home接口,并进行强制类型转换。例如:

ExampleHome home  =(ExampleHome)getContext().lookup(Example_JNDI_NAME);

注意,默认时,通过lookup查找来的对象是由sun.misc.Launcher加载的。但是在Eclipse插件中引用的ExampleHome是由eclipse本身加载的,所以上述转换在eclipse环境中将产生cast error.解决的办法就是让ExampleHome这些远程接口全部由sun.misc.Launcher加载,最简便的办法就是把这些包放入java系统路径下,作为系统组件由jvm加载。

    另外一种解决方式就是创建特定的InitialContextFactoryBuilder,使之从eclipse里加载。

    NamingManager具有一个静态方法setInitialContextFactoryBuilder,可以安装一个InitialContextFactoryBuilder。采用这点,参考java的实现,可以编写特定的Context工厂类,从而从eclipse中加载相应的资源。这样就可以避免转换错误。如下代码所示:

public static InitialContext getContext() throws NamingException {

    if (initialContext == null) {

    //同步

        synchronized (syncObj) {

           if (initialContext == null) {

               Hashtable props = new Hashtable();

              props.put(InitialContext.INITIAL_CONTEXT_FACTORY,

                         "org.jnp.interfaces.NamingContextFactory");

              props.put(InitialContext.PROVIDER_URL,

                         "jnp://127.0.0.1:1099");

              //使用自定义InitialContextFactoryBuilder

              NamingManager.setInitialContextFactoryBuilder(new

SoftappInitialContextFactoryBuilder());

              initialContext = new InitialContext(props);            

              }

           }

       }

       return initialContext;

    }

 

class SoftappInitialContextFactoryBuilder implements

InitialContextFactoryBuilder{

    public InitialContextFactory

createInitialContextFactory(Hashtable env) throws NamingException {

       InitialContextFactory factory;

       String className = env != null ?

             (String)env.get(Context.INITIAL_CONTEXT_FACTORY) : null;

       if (className == null) {

           NoInitialContextException ne = new

NoInitialContextException(

              "Need to specify class name in environment or system " +

              "property, or as an applet parameter, or in an " +

              "application resource file:  " +

               Context.INITIAL_CONTEXT_FACTORY);

           throw ne;

         }

         try {

              //注意此句,this.getClass().getClassLoader()获得的类加载器

              //正是eclipse的类加载器,从而在调用getContext().lookup

//能得正确的类

factory = (InitialContextFactory)     

this.getClass().getClassLoader().

loadClass(className).newInstance();

         } catch(Exception e) {

              NoInitialContextException ne =

                  new NoInitialContextException(

                      "Cannot instantiate class: " + className);

              ne.setRootCause(e);

              throw ne;

         }

         return factory;

    }

 

    类似的问题存在于eclipse环境中使用hibernatehibernate在解析*.hbm.xml时会查找相应的类文件并进行加载。当hibernate本身作为插件插入到eclipse中时,那么*.hbm.xml对应的类文件必须放置到hibernate插件本身中去(可以通过库的方式加载),否则也会由于加载的线程不同造成类转换错误。

 

    另外注意,eclipse的插件不允许循环引用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值