Spring作为JNDI提供者?

时间:2010-12-10 23:09:59

标签: java spring jndi

我想将Spring用作JNDI提供程序。这意味着我想在Spring上下文中配置一个bean,可以通过JNDI访问它。这看起来像这样:

<bean class="org.some.thing.here">
    <property name="beans">
        <map>
            <entry key="w/t/f">
                <bean class="some.thing.Else">
                     // rest ommitted
                </bean>
            </entry>
        </map>
    </property>
</bean>

然后,在我的应用程序(比如说一个Controller)中,我希望能够通过以下方式获取这个bean:

Context ctx = new InitialContext();
some.thing.Else bar = (some.thing.Else) ctx.lookup("w/t/f");

我怎么能这样做?我看过XBean,但项目看起来已经过时了(不适用于Spring 3.0.X我不认为),而且文档很少。

还有其他选择吗?如果不是很难做的话,我也会考虑推出自己的jndi提供者课程。

编辑:我应该补充一点,我没有使用JNDI的选项,我有一个我们必须使用的库,需要通过JNDI加载某些组件。我想使用Spring作为提供者。

3 个答案:

答案 0 :(得分:5)

为什么要使用JNDI?只需获取Spring ApplicationContext并从中获取bean。

假设您在webapp中使用ContextLoaderListener初始化Spring,您应该能够从ServletContext中检索应用程序上下文。从那里你可以获得你在Spring中声明的任何bean。

ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext);
Object bean = context.getBean(some.thing.Else.class);

<击>

如果必须使用JDNI,那么可以创建一个ServletContextListener,它在contextInitialized()中执行类似下面的操作:

ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext);

Object bean = context.getBean(some.thing.Else.class);

Context initCtx = new InitialContext();
Context springCtx = initCtx.createSubcontext("spring");

springCtx.bind("bean", bean);

然后,您应该能够从InitialContext中的“spring / bean”中查找Spring bean。

有两点需要注意:

  1. 上下文侦听器也应该在contextDestroy中调用initCtx.destroySubcontext(“spring”)。

  2. java:comp / env命名空间是只读的(至少在Tomcat中),所以你不能放任何东西。


  3. Asker编辑:还有几点清晰度......

    如果您打算通过ApplicationContext引用Spring bean,那么您需要在web.xml中定义ContextLoaderListener。这必须在自定义侦听器类之前定义...如下所示:

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    <listener>
        <listener-class>
        org.example.sandbox.MyCustomServletContextListener
      </listener-class>
    </listener> 
    

    此外,您可以从ServletContext获取getWebApplicationContext使用的ServletContextEvent,如下所示:

    @Override
    public void contextInitialized(ServletContextEvent contextEvent) {
        try {
            ApplicationContext appContext = WebApplicationContextUtils.getWebApplicationContext(contextEvent.getServletContext());
    
            // get a bean named "myCalendar" from the application context       
            Calendar cal = (Calendar)appContext.getBean("myCalendar");
    
            // bind via JNDI
            Context initialContext = new InitialContext();
            Context subCtx = initialContext.createSubcontext("sample");
            subCtx.bind("calendar", cal);
    
        } catch (NamingException e) { // ommitted }
    }
    

答案 1 :(得分:2)

AngerClown是对的,不要打扰JNDI,除非你需要提供对其他坚持的模块的引用。如果您在像Tomcat这样的webapp容器中,它将具有JNDI注册表。用那个。如果不在webapp容器中,那么无论如何都没有JNDI,因为它适用于J2EE环境。

假设您在webapp中,启动应用程序的更好方法是让主类成为实现生命周期接口(如InitializingBean)的Spring bean,以便在启动应用程序时进行调用。到那时,您的主应用程序类将被注入所有依赖项。这避免了直接在ApplicationContext上调用方法的需要。

即便如此,如果你必须在ApplicationContext上调用方法并且由Spring启动,你可以实现BeanContextAware并注入上下文。

答案 2 :(得分:1)