L'Injection de autocâblés dépendances a échoué lors de l'utilisation de @Transactional
Je test mon DAO, mais il ne fonctionne pas. L'erreur suivante se produit:
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
Mon DAO:
@Service
@Scope("singleton")
public class HibernateController extends HibernateDaoSupport {
@Autowired
public SessionFactory sessionFactory;
@Transactional
public void addAcount(Account account) {
sessionFactory.getCurrentSession().saveOrUpdate(account);
}
}
Mon test pour ce 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"));
}
}
Mon 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>
Je note, que si vous commentaire @Transactional dans DAO, haricot est créé correctement. Ce qui se passe?
BTW, à mon humble avis, pour les classes DAO il est préférable d'utiliser
@Repository
annotation au lieu de @Service
.
OriginalL'auteur tsekhan | 2012-03-22
Vous devez vous connecter pour publier un commentaire.
Tout d'abord son vraiment mauvais de donner un nom se terminant par un Contrôleur à un DAO sa très confus, de Contrôleur et de DAO ont d'autre but.
Lorsque vous ajoutez
@Transactional
d'un service ou d'une classe dao, pour le printemps pour le faire fonctionner dans une transaction doit créer un proxy de la classe, son une sorte de wrapper où en avant l'exécution de proxy classe(la classe en considération, ce qui est mandaté) méthode de printemps commence l'opération et après l'exécution dans le cas où aucune des exceptions termine la transaction, ce qui peut être fait au printemps via AOP et les Annotations. Pour décrire dans le code.Comme vous le voyez ce n'est pas exact de mise en œuvre, mais un code de la fondation, la façon dont la transaction comme par magie fonctionne pour vous. Le point clé est-il de l'interface OriginalDao qui rend cette injection facile que OriginalDaoImpl et ProxyDaoImpl implémentent la même interface. Par conséquent, ils peuvent être échangés à savoir proxy prenant la place de l'original. Cette dynamique proxy peuvent être créés en java en Java dynamique proxy. Maintenant, la question que faire si votre classe n'est pas la mise en œuvre d'une interface, il devient plus difficile pour le remplacement d'arriver.
L'une des bibliothèques CGLIB autant que je sache, aide dans un tel scénario, où il génère une dynamique sous-classe de la classe dans l'examen et dans surchargée de la méthode effectue la magie comme décrit ci-dessus, en appelant
super.save(o)
de déléguer au code d'origine.Maintenant au problème de l'injection.
proxy-target-class="true"
attribut<tx:annotation-driven transaction-manager="transactionManager"/>
Aussi loin que l'exception, il est en train de lancer comme il est attendu bean injecté pour être de type 'HibernateController" mais ses pas.
Pour vous de référence, vous pouvez consulter les liens ci-dessous.
Espérons que cette aide !!!!!.
proxy-target-class="true"
lors de l'injection des interfaces. Aussiproxy-target-class="true"
cassera@Transactional
sur les interfaces. Outre que: +1.oui, ce n'est pas sur mon esprit, bien que vous avez ajouté
Grande réponse et bonne explication
merci !!
J'ai eu @Autowire pas sur l'interface, mais la classe... merci
OriginalL'auteur baba.kabira
Si vous utilisez
Spring MVC
assurez-vous d'analyser des classes de contrôleur seul dansservlet context file
. Sinon, il va scanner 2 fois et l'opération n'est pas disponible sur le contexte de l'application.OriginalL'auteur Anbarasan