我测试了我的DAO,但是没有用。发生以下错误:
Tests in error: testAccountOperations(com.tsekhan.rssreader.dao.HibernateControllerTest): Error creating bean with name 'com.tsekhan.rssreader.dao.HibernateControllerTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.tsekhan.rssreader.dao.HibernateController com.tsekhan.rssreader.dao.HibernateControllerTest.hibernateController; nested exception is java.lang.IllegalArgumentException: Can not set com.tsekhan.rssreader.dao.HibernateController field com.tsekhan.rssreader.dao.HibernateControllerTest.hibernateController to $Proxy25
我的DAO:
@Service @Scope("singleton") public class HibernateController extends HibernateDaoSupport { @Autowired public SessionFactory sessionFactory; @Transactional public void addAcount(Account account) { sessionFactory.getCurrentSession().saveOrUpdate(account); } }
我对此DAO的测试:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:/applicationContext.xml") public class HibernateControllerTest { @Autowired HibernateController hibernateController; private Set<Channel> getTestChannelList(String channelLink) { Channel testChannel = new Channel(); testChannel.setSourceLink(channelLink); Set<Channel> testChannelList = new HashSet<Channel>(); testChannelList.add(testChannel); return testChannelList; } private Account getTestAccount(String accountLogin, String channelLink) { Account testAccount = new Account(); testAccount.setAccountLogin(accountLogin); testAccount.setChannelList(getTestChannelList(channelLink)); return testAccount; } @Test public void testAccountOperations() { hibernateController .addAcount(getTestAccount("test_login", "test_link")); } }
我的 applicationContext.xml :
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd" default-autowire="byName"> <!-- Enabling spring-transaction annotations --> <tx:annotation-driven transaction-manager="transactionManager"/> <!-- Enabling annotation-driven configurating --> <context:annotation-config /> <!-- Creation of transaction manager --> <bean id="transactionManager" scope="singleton" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <bean id="sessionFactory" scope="singleton" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="configLocation" value="classpath:/hibernate.cfg.xml"/> <property name="configurationClass"> <value>org.hibernate.cfg.AnnotationConfiguration</value> </property> </bean> <!-- A Spring interceptor that takes care of Hibernate session lifecycle. --> <bean id="hibernateInterceptor" class="org.springframework.orm.hibernate3.HibernateInterceptor"> <property name="sessionFactory"> <ref bean="sessionFactory"/> </property> </bean> <bean name="employeeDAO" scope="prototype" class="com.tsekhan.rssreader.dao.HibernateController" /> <!-- Searching for hibernate POJO files in package com.tsekhan.rssreader.web --> <context:component-scan base-package="com.tsekhan.rssreader.web" /> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" /> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" /> </beans>
我注意到,如果您在DAO中评论@Transactional,则将正确创建bean。怎么了?
首先,将以Controller结尾的名称给DAO确实很令人困惑,Controller和DAO共同具有不同的目的。
当您添加@Transactional到服务或dao类时,为了使Spring在事务中起作用,需要创建该类的代理,它是一种包装,在执行代理类(考虑类的方法)之前spring启动事务,在执行之后,如果没有异常完成事务,则可以在spring中通过AOP和Annotations完成。用代码描述。
@Transactional
public class OriginalDaoImpl implements OriginalDao extends DaoSupport { public void save(Object o){ manager.save(o); } } public class ProxyDaoImpl implements OriginalDao { private OriginalDao originalDaoImpl; //instance of OriginalDaoImpl public void save(Object o){ try{ transaction.start(); originalDaoImpl.save(o); transaction.commit(); }catch(Exception e){ transaction.rollback(); }finally{ //clean up code } } }
如您所见,这不是确切的实现,而是基础代码,说明事务如何神奇地为您工作。关键在于接口OriginalDao,由于OriginalDaoImpl和ProxyDaoImpl都实现了相同的接口,因此可以轻松进行注入。因此,它们可以交换,即代理代替原始文件。可以通过Java动态代理在Java中创建此动态代理。现在,问题是如果您的类未实现接口,那么替换将变得更加困难。据我所知,CGLIB库之一在这种情况下会有所帮助,在这种情况下,它会为所考虑的类生成一个动态子类,并且在覆盖方法中,它通过调用super.save(o) 委托给原始代码来执行上述操作。
super.save(o)
现在开始注射问题。
proxy-target-class="true"
<tx:annotation-driven transaction-manager="transactionManager"/>
就异常而言,它正在抛出,因为它期望注入的bean是’HibernateController’类型的,但不是。
供您参考,您可以参考下面的链接。
希望这可以帮助 !!!!!。