我测试了我的 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
My 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"));
}
}
My 应用程序上下文.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 和注解来完成。用代码来描述。
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)
委托给原始代码。
现在来说说注射的问题。
- 创建接口并让你的 dao 实现它,spring 将默认使用 JDK 代理,就像它现在的行为一样。
- Add
proxy-target-class="true"
归因于<tx:annotation-driven transaction-manager="transactionManager"/>
就异常而言,它正在抛出,因为它期望注入的 bean 为“HibernateController”类型,但事实并非如此。
您可以参考下面的链接供您参考。
- 10.5.6 使用@Transactional http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html
- Spring AOP 文档 http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html
希望这可以帮助 !!!!!。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)