为什么使用JndiObjectFactoryBean来配置JNDI数据源不起作用?

当我使用Java-base来配置我的JNDI时。 spring4.2.5。

但是如果我使用JndiObjectFactoryBean来配置。当我想获取datasource ,该对象将为null。

 @Bean public DataSource dataSource(){ JndiObjectFactoryBean jndiObjectFactoryBean =new JndiObjectFactoryBean(); jndiObjectFactoryBean.setJndiName("jdbc/SpittrDS"); jndiObjectFactoryBean.setResourceRef(true); jndiObjectFactoryBean.setProxyInterface(DataSource.class); return (DataSource) jndiObjectFactoryBean.getObject(); //NULL!!! } 

但如果将方法更改为此,则效果很好。

 @Bean public DataSource dataSource(){ final JndiDataSourceLookup dsLookup = new JndiDataSourceLookup(); dsLookup.setResourceRef(true); DataSource dataSource = dsLookup.getDataSource("java:comp/env/jdbc/SpittrDS"); return dataSource; } 

我不知道问题出在哪里。

Tomcat 9.0 context.xml

    WEB-INF/web.xml ${catalina.base}/conf/web.xml  <!--  -->   

JndiObjectFactoryBean中的实际查找是在生命周期回调方法中完成的。 在这个@Bean方法中明确地调用方法(解决方法)

  @Bean public DataSource dataSource(){ JndiObjectFactoryBean jndiObjectFactoryBean =new JndiObjectFactoryBean(); jndiObjectFactoryBean.setJndiName("jdbc/SpittrDS"); jndiObjectFactoryBean.setResourceRef(true); jndiObjectFactoryBean.setProxyInterface(DataSource.class); jndiObjectFactoryBean.afterPropertiesSet(); return (DataSource) jndiObjectFactoryBean.getObject(); //NULL!!! } 

或者更好的方法。 让你的@Bean方法返回JndiObjectFactoryBean并管理它的生命周期。 然后在需要DataSource的依赖bean中注入从工厂创建的数据源

  @Bean public JndiObjectFactoryBean dataSource(){ JndiObjectFactoryBean jndiObjectFactoryBean =new JndiObjectFactoryBean(); jndiObjectFactoryBean.setJndiName("jdbc/SpittrDS"); jndiObjectFactoryBean.setResourceRef(true); jndiObjectFactoryBean.setProxyInterface(DataSource.class); return jndiObjectFactoryBean; } //in your dependnecy @Bean public SomeBean someBean(DataSource dataSource){ //use the injected datasource shich comes from the factory } 

我在这里登陆而没有意识到这是我过去遇到的一个问题 – 错误将Spring的JndiObjectFactoryBean转换为Solace-MQ JMS的ConnectionFactory

所以解决方法(不是首选的方法)是在尝试getObject()之前在jndiObjectFactoryBean上调用afterPropertiesSet()

 @Bean public DataSource dataSource(){ JndiObjectFactoryBean jndiObjectFactoryBean =new JndiObjectFactoryBean(); jndiObjectFactoryBean.setJndiName("jdbc/SpittrDS"); jndiObjectFactoryBean.setResourceRef(true); jndiObjectFactoryBean.setProxyInterface(DataSource.class); jndiObjectFactoryBean.afterPropertiesSet(); return (DataSource) jndiObjectFactoryBean.getObject(); //NOT NULL }