Java Spring正在注入具体的类而不是代理

Java Spring正在注入具体的类而不是代理,java,spring,jpa,Java,Spring,Jpa,我有一个问题,Spring将DAO对象的代理注入到服务中,但这个服务被注入到控制器中,因为它是具体的类。这不允许我使用服务范围的事务,并分别为每个DAO调用启动事务。这是我所期望的行为 配置: 控制器是带有@Controller注释和构造函数DI的类 服务: @组成部分 @交易的 公共类UserServiceImpl实现UserService{…} 道: @组成部分 @交易的 公共类UserDaoImpl实现UserDao{ JPA配置: ${hibernate.dial} ${hibe

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

配置:

控制器是带有@Controller注释和构造函数DI的类

服务:

@组成部分 @交易的 公共类UserServiceImpl实现UserService{…} 道:

@组成部分 @交易的 公共类UserDaoImpl实现UserDao{ JPA配置:


${hibernate.dial}
${hibernate.show_sql}
${hibernate.format_sql}
${hibernate.hbm2ddl.auto}

有人知道为什么会发生这种情况吗?

我在理解你说的话时有点困难,但是你似乎很惊讶,每次DAO调用都会得到一个新的事务,而不仅仅是在服务调用上。不幸的是,这正是你通过放置“@Transactional”指定的在DAO类上。您的DAO不应该是事务性的,至少如果您遵循通常的模式。如果我理解正确,您应该删除DAO类上的@transactional注释。

您不应该使用“@transactional”DAO对象中的注释。您正在服务中定义它,这将允许在服务方法中调用的所有DAOs方法在同一事务中执行,这似乎正是您所希望的,当您说“服务范围事务”时,对吗

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


致以最诚挚的问候。

其他响应者是正确的,因为您不应该将DAO注释为
@Transactional
,但要真正了解正在发生的事情,您应该参考。使用
@Transactional
时的默认传播是
需要传播,因此请具体查看

你的问题没有那么具体,所以我不确定你到底在找什么


编辑:重新阅读您的问题后,您的组件扫描可能存在问题。请检查以确保您的
与您的组件扫描服务类时所处的应用程序上下文相同。

您的
UserServiceImpl
很可能是错误创建的-请检查
context:component scan
表达式,检查其中是否只包含
Controller

看 有关组件扫描过滤器的示例

例如,如果在中声明了事务管理器bean和
,则将仅为根应用程序上下文中的bean创建事务代理(从):

BeanPostProcessor接口的作用域为每个容器。这只是 如果使用容器层次结构,则与此相关。如果定义 BeanPostProcessor在一个容器中,它将只在 容器中的bean。在一个容器中定义的bean是 不由另一个容器中的BeanPostProcessor进行后期处理,即使 如果两个容器都是同一层次结构的一部分

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

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

有关Spring中事务传播的参考,请参阅


例如,在Spring Data JPA中(我很确定他们知道自己在做什么),这在某些情况下可能很有用,其机制与Hibernate允许您从
会话中获取()一些任意对象以显示而不声明显式事务时的机制相同(当然,这并不意味着框架能够在没有事务的情况下运行——这在本例中是隐含的).

我会在服务上舍弃'@Component'并放置'@service'原型注释。至于dao,我会放置'@Repository'注释并舍弃组件注释。此外,'@Transactional'属性意味着服务的每个方法都将具有相同的事务传播。我会对我的每个方法进行注释HOD分别取决于它们应该做什么。我添加了一个答案,因此请检查您的事务配置xml文件是否由声明用户服务的同一位置处理。请随意提出进一步的问题-1如果我在每次DAO调用中也得到一个新的事务,当我的应用程序服务ice用
@Transactional
注释(Propagation.REQUIRED硬编码为
中传播的默认值)
@Component
@Transactional
public class UserServiceImpl implements UserService { ...}
@Component
@Transactional
public class UserDaoImpl implements UserDao {
<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 />