【问题标题】:How do I instantiate an attribute that is declared as a bean in the spring config?如何实例化在 spring 配置中声明为 bean 的属性?
【发布时间】:2015-06-30 23:39:26
【问题描述】:

我正在尝试解决一个非常简单的解决方案:

我有我的 DAO 对象:

package com.me.dao;
@Service
public class JavaNeo4jConnection implements Neo4jConnection {
    private JdbcTemplate jdbcTemplate;

    @Autowired(required = true)
    private DriverManagerDataSource dataSource;

    public void setDataSource(DriverManagerDataSource dataSource) {
        this.dataSource = dataSource;
        this.jdbcTemplate = new JdbcTemplate(this.dataSource);
    }

}

我已经在 springConfig.xml 中声明了数据源

<context:annotation-config />
<context:component-scan base-package="com.me.dao" />
<context:component-scan base-package="com.me.servlets" />

<!-- Servlet --> 
<bean id="viewResolver"
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass"
        value="org.springframework.web.servlet.view.JstlView" />
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" />
</bean>

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

<!-- Config properties file-->
<bean
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath:config.properties</value>
        </list>
    </property>
</bean>

正在使用我的 servlet 控制器中的自动装配来实例化 dao 对象:

package com.me.servlets;

@Controller
public class JsonServer {
    @Autowired
    Neo4jConnection neoConn;

    @RequestMapping("/servejson")
    @ResponseBody
    public void serveJson(HttpServletRequest request, HttpServletResponse response
    ) throws IOException {

        OutputStream os = response.getOutputStream();       

        String json =  neoConn.getInfo(request.getParameter("query"));

        os.write(json.getBytes());
        os.close();
        os.flush();

    }

}

但是数据源永远不会被实例化,运行我的代码会产生一个NullPointerException

我在这里缺少什么?我很确定我在滥用@Autowired

【问题讨论】:

  • 你从哪里得到NullPointerException?你在哪里以及如何使用JavaNeo4jConnection bean?
  • 您是否对包含JavaNeo4jConnection 类的包进行组件扫描? JavaNeo4jConnection 必须是 bean 才能使其字段自动装配。发布整个配置文件。
  • 您可能会在 jdbcTemplate 上获得 npe,如果是这样,请尝试将 autowire 注释放在 setter 上
  • 需要看看你是如何使用JavaNeo4jConnection类的。
  • @SotiriosDelimanolis 将@Autowired 注释添加到方法中修复了它。您能否将其发布为答案并解释 @Autowired 在应用于方法和属性方面的工作原理?

标签: java spring nullpointerexception instantiation


【解决方案1】:

给定

@Service
public class JavaNeo4jConnection implements Neo4jConnection {

<context:component-scan ... />
// or <context:annotation-config /> which is redundant if you have the 'component-scan'

Spring 将实例化您的 JavaNeo4jConnection bean。在此过程中,它将扫描班级成员以查找@Autowired(以及其他内容)。如果它找到一个用它注释的字段,它将尝试解析一个 bean 并注入它。如果它找到一个带有注解的方法,它会查看参数并尝试解析适当的 bean,并在调用该方法时将它们用作参数。

因为你只有一个带注释的字段

@Autowired
Neo4jConnection neoConn;

Spring 将直接使用字段注入。它将找到的 bean 分配给该字段。它不会调用您的 setter 方法,因此不会初始化 JdbcTemplate 字段。

一种解决方案是将注解移至setter方法(方法注入)。

使用字段注入的另一种解决方案是将您的 setter 方法替换为 @PostConstruct 带注释的方法

@PostConstruct
public void init() {
    // dataSource has been injected
    this.jdbcTemplate = new JdbcTemplate(this.dataSource);
}

或者使用构造函数注入

@Autowired
public JavaNeo4jConnection(DriverManagerDataSource dataSource) {
    this.dataSource = dataSource;
    this.jdbcTemplate = new JdbcTemplate(this.dataSource);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-28
    • 2010-10-05
    • 2014-12-25
    • 1970-01-01
    • 2018-01-16
    • 2020-11-24
    相关资源
    最近更新 更多