当前位置: 首页 > 面试题库 >

使用@Transactional时自动连接依赖项的注入失败

洪伟兆
2023-03-14
问题内容

我测试了我的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完成。用代码描述。

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)
委托给原始代码来执行上述操作。

现在开始注射问题。

  1. 创建接口并让您的dao实现该功能,并且spring将默认使用JDK代理,因为它现在正在运行。
  2. proxy-target-class="true"属性添加到<tx:annotation-driven transaction-manager="transactionManager"/>

就异常而言,它正在抛出,因为它期望注入的bean是’HibernateController’类型的,但不是。

供您参考,您可以参考下面的链接。

  1. 10.5.6使用@Transactional
  2. springAOP文件

希望这可以帮助 !!!!!。



 类似资料:
  • 问题内容: 我正在开发一个小型Java EE Hibernate Spring应用程序,出现错误: 这是我的控制器ArticleControleur,其中包含用于恢复文章列表的功能: 这是我的articleService: 这是我的应用程序上下文: 问题答案: 该错误表明不是注册的Bean。添加其中包含将在你的应用程序上下文中自动装配的bean的软件包: 或者,如果你想将所有子包包括在com.bd

  • 大家好,我收到下一个错误,我是使用Hibernate的新手

  • 这是我的当前设置:ProjectRepo: ProjectService: ProjectRestController:

  • 下面是演示该问题的代码。Class3具有Class2的自动生成字段,Class2具有Class1的自动生成依赖项,简单测试使用Class3获取Class1的String值。因此,在测试执行中,Class2不是空的,并被注入到Class3中,但是Class2中的Class1是空的。

  • 被异常卡住,下面是日志: org.springframework.beans.factory.BeanCreation异常:创建名为扬声器的bean时出错:注入自动生成的依赖项失败;嵌套异常是org.springframework.beans.factory.BeanCreation异常:无法自动连接方法:公共最终无效org.mybatis.spring.support.SqlSessionDao

  • 我在Spring+SpringMVC+Hibernate+MySQL web应用程序中的Spring配置有一个问题。Spring无法创建我在Service类中宣布的bean。 下面是Controller类 应用程序-上下文 最后是我的StackTrace 原因:org.SpringFramework.Beans.Factory.BeanCreationException:无法自动连接字段:priv