Spring bean已创建但未自动装配

 mobiledu2502861847 发布于 2023-02-07 16:25

我试图在Spring中运行DAO类的TestNG测试.但是,尽管有注释,DataSource引用仍未自动装配.以下是测试的一部分:

@ContextConfiguration(locations={"classpath:WEB-INF/servlet-context.xml"})
public class ToDoDaoImplTest extends AbstractTestNGSpringContextTests {

    @Autowired
    // Construction of this object fails
    private ToDoItemDaoImpl toDoDao;
}

这是我的Spring配置:


    
    




    
    
    
    



    



DAO类:

@Repository
public class ToDoItemDaoImpl implements ToDoItemDao {
    private DataSource dataSource;
    private SimpleJdbcInsert insert;

    public ToDoItemDaoImpl() {
        // dataSource is null here
        insert = new SimpleJdbcInsert(dataSource).withTableName("toDoItem").usingGeneratedKeyColumns("id");
    }

    @Autowired
    @Qualifier("dataSource")
    // This method is not called by Spring
    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

这是错误的堆栈跟踪:

Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.myapp.dao.ToDoItemDaoImpl]: Constructor threw exception; nested exception is java.lang.IllegalArgumentException: Property 'dataSource' is required
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:163)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1004)
    ... 50 more
Caused by: java.lang.IllegalArgumentException: Property 'dataSource' is required
    at org.springframework.jdbc.support.JdbcAccessor.afterPropertiesSet(JdbcAccessor.java:134)
    at org.springframework.jdbc.core.JdbcTemplate.(JdbcTemplate.java:165)
    at org.springframework.jdbc.core.simple.AbstractJdbcInsert.(AbstractJdbcInsert.java:97)
    at org.springframework.jdbc.core.simple.SimpleJdbcInsert.(SimpleJdbcInsert.java:60)
    at org.myapp.dao.ToDoItemDaoImpl.(ToDoItemDaoImpl.java:33)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:148)
    ... 52 more
null

显示dataSource的部分日志:

DEBUG - DefaultListableBeanFactory - Creating shared instance of singleton bean 'dataSource'
DEBUG - DefaultListableBeanFactory - Creating instance of bean 'dataSource'
DEBUG - DefaultListableBeanFactory - Eagerly caching bean 'dataSource' to allow for resolving potential circular references
INFO  - DriverManagerDataSource    - Loaded JDBC driver: org.h2.Driver
DEBUG - DefaultListableBeanFactory - Finished creating instance of bean 'dataSource'
DEBUG - DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.jdbc.datasource.init.DataSourceInitializer#0'
DEBUG - DefaultListableBeanFactory - Creating instance of bean 'org.springframework.jdbc.datasource.init.DataSourceInitializer#0'
DEBUG - DefaultListableBeanFactory - Eagerly caching bean 'org.springframework.jdbc.datasource.init.DataSourceInitializer#0' to allow for resolving potential circular references
DEBUG - DefaultListableBeanFactory - Returning cached instance of singleton bean 'dataSource'

这让我很困惑.已创建dataSource对象,但未将其自动装入Spring管理的对象中.我究竟做错了什么?

1 个回答
  • 问题在这里

    public ToDoItemDaoImpl() {
        // dataSource is null here
        insert = new SimpleJdbcInsert(dataSource).withTableName("toDoItem").usingGeneratedKeyColumns("id");
    }
    

    Spring只能在创建对象后自动装配字段.这在构造函数完成后发生.

    Spring将使用反射,即.类似的Class.forName(yourClass).newInstance(),创建你的bean,然后再次使用反射来设置每个属性.

    但是,在构造函数中,该字段仍然null是所有未初始化的引用类型字段的默认值.

    一种解决方案是将构造函数留空并添加带@PostConstruct注释的方法

    @PostConstruct
    public void init() {
        insert = new SimpleJdbcInsert(dataSource).withTableName("toDoItem").usingGeneratedKeyColumns("id");
    }
    

    另一种解决方案是在setDataSource()方法内添加初始化.

    2023-02-07 16:29 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有