【问题标题】:Spring injecting or autowiring datasource bean to classSpring将数据源bean注入或自动装配到类
【发布时间】:2013-07-23 02:05:43
【问题描述】:

这可能是一个非常新手的问题,但我已经搜索过,要么我的理解存在很大差距,要么我做错了我无法弄清楚的事情。

在我的上下文文件中,这是一段摘录

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${datasource.driverClassName}" />
    <property name="url" value="${datasource.url}" />
    <property name="username" value="${datasource.username}" />
    <property name="password" value="${datasource.password}" />
</bean>

<bean id="myBeanOne" class="a.b.c.myBeanOne">
         <property name="dataSource" ref="dataSource" />
</bean>

现在在 myBeanOne 我有:

private DataSource dataSource;

private JdbcTemplate jdbcTemplate;

@Autowired
public void setDataSource (DataSource dataSource) {
    this.jdbcTemplate = new JdbcTemplate(dataSource);
}

public void myMethod() {
    String sql = "'My generic SQL update query'";
    try {
        this.jdbcTemplate.update(sql);
    } catch (org.springframework.dao.EmptyResultDataAccessException ex) {
    }
    System.exit(0);
}

当我尝试在调用 setDataSource 的行上执行此操作时,我收到此错误:

ERROR org.springframework.integration.handler.LoggingHandler 
    org.springframework.integration.MessageHandlingException: 
       java.lang.NullPointerException

在线:this.jdbcTemplate.update(sql);

我已经尝试了十种不同的配置来让它工作,但我似乎做不到。感谢您提供任何帮助,谢谢。

编辑:根据 Luiggi 的评论:

//in yet another classes run method
myBeanOne bOne = SomeOtherClass.create();   //just returns new myBeanOne
bOne.myMethod();

SomeOtherClass 或此类在上下文中均未分类为 bean,也不存在于上下文中。

我知道这是一个非常基本的问题,但我正在努力解决它。

感谢您的耐心等待。

【问题讨论】:

  • 你错过了主要问题:你怎么打电话给MyBeanOne#myMethod
  • 正在从另一个类(不在上下文文件中)调用它。
  • 检查是否在堆栈跟踪中看到任何错误,如果未建立数据库连接,则会发生这种情况。除此之外,我没有看到代码问题。
  • @Phani 错误是NullPointerException(再读一遍问题)。
  • 在你使用这个MyBeanOne实例的地方添加代码,可能是你没有正确使用它或自己初始化它,从而在myMethod中使用jdbcTemplate变量时得到NPE。跨度>

标签: java spring jdbc autowired


【解决方案1】:

如 cmets 中所述,问题在于您手动创建 bean,而不是让 Spring 容器创建它。基本上,您正在这样做:

new MyBeanOne()

因此 Spring 容器无法注入您配置的任何字段,因此为 null 例如jdbcTemplate 字段。有一些解决方案:

  1. 将你的SomeOtherClass转换成Spring容器管理的bean,让它注入MyBeanOne实例(可能使用@Autowired注解)。

  2. 如果由于您需要手动创建 bean 而无法完成后一种方法,您可以手动创建 bean,如下所示:How to create spring beans dynamically?

    但是这个实现让你在某处硬编码 spring 配置文件名并在你的代码中使用它。因此,更好的方法是选项 3。

  3. 看看这个解决方案:Creating New Spring Beans on Demand,您可以在其中创建一个客户端抽象类,其中包含 Spring 将实现的方法来检索 Spring 托管 bean 的新实例。


我找到了另一种使用@Configurable 注释来处理这个问题的方法。通过使用此注解装饰您的 bean,您可以按需创建 bean 的新实例,Spring 将为您管理 Spring 托管 bean 的注入。但要实现这一点,Spring 需要在幕后使用方面,您应该为您的项目激活方面的使用。解释很长,所以我提供了深入解释这个解决方案的链接:

请注意,为了启用此功能,您必须在启动 JVM 时添加一个 java 代理,该代理将在运行时使用方面编织类。

【讨论】:

    【解决方案2】:

    NullPointerException上线:this.jdbcTemplate.update(sql);

    如果 NPE 实际上在那条线上,那么this.jdbcTemplate 显然是null。如果这是真的,那么:

    • setDataSource(...) 方法在 Spring 中没有被调用,可能是因为 @Autowired 不正确。很容易添加System.out.println(...) 或在setDataSource 中放置调试断点以查看它是否被调用。

    • 如果它正在被调用,那么a.b.c.myBeanOne 的实例可能不止一个?您确定要从 Spring 上下文中的另一个类调用实例吗?在setDataSource 中放置一个断点并注意this 对象引用ID。然后在this.jdbcTemplate.update(...)这一行下断点,确保thisreference-id是一样的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多