java - Spring正在注入(inject)具体类而不是代理

标签 java spring jpa

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

配置:

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

服务:

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

Dao:

@Component
@Transactional
public class UserDaoImpl implements UserDao {

JPA Config:

<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已创建 in the servlet context错误-请检查context:component-scan只检查 Controller 的表达式类包含在那里。

参见 @Service are constructed twice 有关组件扫描过滤器的示例。

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

BeanPostProcessor interfaces are scoped per-container. This is only relevant if you are using container hierarchies. If you define a BeanPostProcessor in one container, it will only do its work on the beans in that container. Beans that are defined in one container are not post-processed by a BeanPostProcessor in another container, even if both containers are part of the same hierarchy.

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

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

参见 http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/transaction.html#tx-propagation供Spring中事务传播引用

在 Spring Data JPA 中(我很确定他们知道自己在做什么),例如,CRUD methods on repository instances are transactional by default .这在某些情况下可能很有用,该机制与 Hibernate 允许您从 Session 中获取()一些任意对象时的机制相同。用于在不声明显式事务的情况下显示(当然这并不意味着框架以某种方式设法在没有事务的情况下进行 - 在这种情况下它是隐含的)。

关于java - Spring正在注入(inject)具体类而不是代理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14587134/

相关文章:

java - android 测试中的 System.out.println

java - 尝试在 Android 中使用全息主题不起作用

java - 在 tomcat Web 服务器中使用参数运行可执行 jar

spring - 在 JoinColumn 注释的字段上编写 CRUDRepository 的 findBy() 方法

java - 优化循环更新请求

java - jOOQ - 使用 refcursor 执行 postgres 用户定义的函数

Wildfly 服务器上的 Java Spring 项目无法访问 RESTful 服务

java - 第二次调用时如何访问 Spring Controller 方法中的参数

java - 我应该 try catch 任何 EnityManager 查询异常吗?

java - JPA存储库通过参数通用方法查找