如何在声明中将(绑定)对象放到jndi中?

我们有一个普通的独立spring应用程序,我们需要将jdbc数据源放在jndi中。 (我们使用jboss treecache,它需要数据源在jndi中)。

一些谷歌搜索发现大多数jndi查找示例与spring,其中一个对象已经放在jndi(通过tomcat或应用程序服务器等),但我们需要:我有一个简单的数据源Spring bean,我注入其他服务,但我无法将其注入TreeCache,因为它只需要来自jndi。

找到org.springframework.jndi.JndiTemplate ,可以声明为bean,例如:

    com.sun.jndi.fscontext.RefFSContextFactory file:///c:\windows\temp    

但是没有找到如何在java代码中绑定它: fsJndiTemplate.bind(name, obj)来自其他bean的init-method。 有没有办法以声明方式做到这一点?

您可以创建一个JndiExporter,它使用JndiTemplate将对象的地图与名称绑定在一起:

            

您的JndiExporter必须实现BeanFactoryAware以使用注入的BeanFactory检索spring bean。

这是一个可能的:)

谢谢你的问题。 我写了一个Treydone解决方案的变体,并认为在这里使用实际代码可能很有用(因为它很短):

 public class JndiExporter implements InitializingBean { private final JndiTemplate template = new JndiTemplate(); private Map jndiMapping = null; @Override public void afterPropertiesSet() throws Exception { for(Entry addToJndi: jndiMapping.entrySet()){ template.bind(addToJndi.getKey(), addToJndi.getValue()); } } public void setJndiMapping(Map jndiMapping) { this.jndiMapping = jndiMapping; } } 

请注意,我实现了InitializingBean而不是BeanFactoryAware。 这允许配置(带引用),如下所示:

         

我意识到这是一个老问题,但有一种方法可以在没有自定义代码的情况下完成此操作。 它相当冗长,但100%声明。

           java:comp/UserTransaction           another/jndi/name literal_value    

只要读取System属性的bean depends-on MethodInvokingFactoryBeanMethodInvokingFactoryBean也可用于设置系统属性( 在使用Atomikos时派上用场 )。

           true true com.atomikos.icatch.standalone.UserTransactionServiceFactory /opt/txlogs     

嗨此问题没有标准或最佳实践类型方法。 您将拥有自己的方法。 以下是另一种可以解决您的问题的方法。

  1. 使javax.naming.InitialContext成为一个spring bean(比如initialContext)。 确保根据需要向其传递适当的初始属性映射。

  2. 现在创建另一个bean说JndiBinder。 在这个bean中注入上面提到的#1 bean。 这个bean将获取jndi-names和相应对象的映射。 对于您的情况,该对象将是数据源,已在spring上下文中可用。

  3. 在JndiBinder bean定义中,编写一个init方法,该方法将为地图中的所有条目(jndi-names和相应对象)调用initialContext的bind menthod。 这样,提供的映射中的所有条目都绑定到JNDI树。

如果代码在Servlet容器外部执行,例如在unit testing中,则需要模拟JNDI上下文。 否则你会得到可怕的“需要在环境中指定类名…”错误。

SimpleNamingContextBuilder比JndiTemplate更适合:

 public class JndiExporter implements InitializingBean { private final SimpleNamingContextBuilder contextBuilder = new SimpleNamingContextBuilder(); private Map jndiMapping = null; @Override public void afterPropertiesSet() throws Exception { for (Entry addToJndi : jndiMapping.entrySet()) { contextBuilder.bind(addToJndi.getKey(), addToJndi.getValue()); } contextBuilder.activate(); } public void setJndiMapping(Map jndiMapping) { this.jndiMapping = jndiMapping; } 

不要忽视“contextBuilder.activate();” 线。