繁体   English   中英

Spring注入具体类而不是代理

[英]Spring is injecting concrete class instead of proxy

我有一个问题,Spring将DAO对象的代理注入到服务中,但是这个服务被注入到控制器中它是具体的类。 这不允许我使用服务范围的事务并分别为每个DAO调用启动事务。 这是我期望的行为。

组态:

Controller是带有@Controller注释和构造函数DI的类。

服务:

@Component
@Transactional
public class UserServiceImpl implements UserService { ...}

道:

@Component
@Transactional
public class UserDaoImpl implements UserDao {

JPA配置:

<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

<bean id="entityManagerFactory"
      class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
    <property name="dataSource" ref="dataSource"/>
    <property name="persistenceUnitName" value="xxxPersistenceUnit"/>
    <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        </bean>
    </property>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
            <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
            <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
        </props>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

<tx:annotation-driven />

任何人都知道为什么会这样?

很可能你的UserServiceImpl在servlet上下文中错误地创建 - 请检查context:component-scan表达式以检查那里只包含Controller类。

有关组件扫描过滤器的示例,请参阅@Service

例如,如果在根Web应用程序上下文中声明了事务管理器bean和<tx:annotation-driven> ,那么将仅为根应用程序上下文中的bean创建事务代理(来自Spring文档 ):

BeanPostProcessor接口的范围是每个容器。 这仅在您使用容器层次结构时才有意义。 如果在一个容器中定义BeanPostProcessor,它将只对该容器中的bean执行操作。 在一个容器中定义的Bean不会被另一个容器中的BeanPostProcessor进行后处理,即使两个容器都是同一层次结构的一部分。

不太可能的是,用户服务的事务配置被配置为使用另一个事务管理器(或另一个默认传播),但在这种情况下, TransactionInterceptor调用将出现在DAO方法的堆栈跟踪中。

如果你明白自己在做什么,那么在Spring中的DAO类上使用@Transactional是绝对可以的 - 存储库或DAO无法打开事务的想法来自于你必须创建一个样板代码来打开事务的黑暗时期。难以管理事务实例(并且您无法确定如何管理事务)。 但是当你使用声明性配置时,事情并没有那么糟糕。 Spring提升了配置约定的风格,大多数方法都使用Propagation.REQUIRED事务模式。 在Spring Propagation.REQUIRED是使用@Transactional装饰方法时的默认模式(此传播被硬编码为@Transactional注释声明),这意味着新的逻辑事务被映射到同一个物理事务,因此使用@Transactional装饰DAO类@Transactional是无害的。

有关Spring中事务传播的参考,请参见http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/transaction.html#tx-propagation

在Spring Data JPA中(我很确定他们知道他们在做什么),例如, 默认情况下,存储库实例上的CRUD方法是事务性的 在某些情况下,这可能很有用,机制与Hibernate允许你从Session获取()一些任意对象进行显示而不声明显式事务(当然这并不意味着框架以某种方式设法在没有事务的情况下进行)相同 - 这种情况隐含在这种情况下)。

我在理解您所说的内容时遇到了一些麻烦,但您似乎对每次DAO呼叫都获得新事务感到惊讶,而不仅仅是在服务呼叫上。 不幸的是,这正是你通过在DAO类上放置“@Transactional”而指定的。 你的DAO不应该是交易性的,至少如果你遵循通常的模式。 如果我理解正确,您应该删除DAO类上的@Transactional注释。

其他响应者是正确的,因为你不应该将你的DAO注释为@Transactional ,但要真正理解发生了什么,你应该参考Spring Reference Manual中Transaction Propagation部分 使用@Transactional时的默认传播是REQUIRES_PROPAGATION ,因此请具体查看。

你的问题不是那么具体,所以我不确定你到底在想什么。

编辑:重新阅读您的问题时,组件扫描可能存在问题。 检查以确保<tx:annotation-driven />与组件扫描服务类的应用程序上下文相同。

您不应该在DAO对象中使用“@Transactional”注释。 您正在服务中定义它,并且授予您在服务方法内部调用的所有DAO方法在同一事务中执行,当您说“服务范围事务”时,这似乎正是您想要的?

另外,如建议的那样,您可能希望在UserServiceImpl中将注释从“@Component”更改为“@Service”,并在UserDaoImpl中将注释更改为“@Repository”。

最好的祝福。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM