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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36575383/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 01:37:30  来源:igfitidea点击:

why use JndiObjectFactoryBean to config JNDI datasource did not work?

javaspringjndi

提问by TIMFUNNY

when I uss Java-base to config my JNDI. Spring 4.2.5.

当我使用 Java-base 来配置我的 JNDI 时。春天 4.2.5。

But If I use JndiObjectFactoryBean to config.when I want to get the datasource,the object will be null.

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

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

But if change the method to this,it work well.

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

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

I do not know where is the problem.

我不知道问题出在哪里。

Tomcat 9.0 context.xml

Tomcat 9.0 上下文.xml

<Context>

    <!-- Default set of monitored resources. If one of these changes, the    -->
    <!-- web application will be reloaded.                                   -->
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>

    <!-- Uncomment this to disable session persistence across Tomcat restarts -->
    <!--
    <Manager pathname="" />
    -->

    <Resource name="jdbc/SpittrDS"
      auth="Container"
      type="javax.sql.DataSource"
      driverClassName="com.mysql.jdbc.Driver"
      url="jdbc:mysql://localhost:3306/spittrds"
      username="root"
      password="1"
      maxActive="100"
      maxIdle="20"
      minIdle="5"
      maxWait="10000"/>
</Context>

回答by ekem chitsiga

The actual lookup in JndiObjectFactoryBean is done in the lifecycle callback method. Either call the method explictly in your @Bean method like this (workaround)

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!!!
    }

Or the better approach. Let your @Bean method return the JndiObjectFactoryBean and manage its lifecyle. Then in your dependent beans that require a DataSource inject the datasource created from the factory

或者更好的方法。让您的@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
}

回答by ObviousChild

I landed here without realizing this was a problem I had faced in the past - Error Casting Spring's JndiObjectFactoryBean to ConnectionFactory for Solace-MQ JMS

我来到这里时没有意识到这是我过去遇到的问题 - Error Casting Spring's JndiObjectFactoryBean to ConnectionFactory for Solace-MQ JMS

So a workaround (not the preferred way) is to call afterPropertiesSet() on jndiObjectFactoryBean before attempting to getObject()

因此,一种解决方法(不是首选方法)是在尝试 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
    }