我想将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作为提供者。
答案 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。
有两点需要注意:
上下文侦听器也应该在contextDestroy中调用initCtx.destroySubcontext(“spring”)。
java:comp / env命名空间是只读的(至少在Tomcat中),所以你不能放任何东西。
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)
编写自己的JndiExporter的另一种方法
https://blog.konstantinpavlov.net/2008/12/31/how-to-export-spring-bean-to-jndi/