JavaSpring正在注入具体的类而不是代理
我有一个问题,Spring将DAO对象的代理注入到服务中,但这个服务被注入到控制器中,因为它是具体的类。这不允许我使用服务范围的事务,并分别为每个DAO调用启动事务。这是我所期望的行为
配置:
控制器是带有@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 />
有人知道为什么会这样吗
# 1 楼答案
其他响应者是正确的,因为您不应该将DAO注释为
@Transactional
,但要真正理解正在发生的事情,您应该参考Transaction Propagation section in the Spring Reference Manual。当使用@Transactional
时,默认的传播是REQUIRES_PROPAGATION
,所以请具体查看你的问题没有那么具体,所以我不确定你到底在找什么
编辑:重新阅读您的问题后,您的组件扫描可能存在问题。检查以确保
<tx:annotation-driven />
处于组件扫描服务类的同一应用程序上下文中# 2 楼答案
我在理解你说的话时有点困难,但你似乎很惊讶,每次DAO调用都会得到一个新的事务,而不仅仅是服务调用。不幸的是,这正是您在DAO类上添加“@Transactional”所指定的。您的DAO不应该是事务性的,至少如果您遵循通常的模式。如果我理解正确,应该删除DAO类上的@Transactional注释
# 3 楼答案
您不应该在DAO对象中使用“@Transactional”注释。您在服务中定义它,这将允许在服务方法中调用的所有DAOs方法在同一事务中执行,这似乎正是您所希望的,当您说“服务范围事务”时,对吗
此外,正如建议的那样,您可能希望在UserServiceImpl中将注释从“@Component”更改为“@Service”,并在UserDaoImpl中将注释从“@Repository”更改为“@Repository”
致以最良好的祝愿
# 4 楼答案
你的
UserServiceImpl
很可能是错误创建的in the servlet context——请检查context:component-scan
表达式,以检查其中是否只包含Controller
类见@Service are constructed twice 有关组件扫描过滤器的示例
例如,如果在root web app context中声明了事务管理器bean和
<tx:annotation-driven>
,那么将仅为根应用程序上下文(从Spring Documentation)中的bean创建事务代理:不太可能的情况是,用户服务的事务配置被配置为使用另一个事务管理器(或另一个默认传播),但在这种情况下
TransactionInterceptor
调用将出现在DAO方法的堆栈跟踪中春季在DAO类上有
@Transactional
是绝对可以的,如果您了解自己在做什么——存储库或DAO无法打开事务的想法来自黑暗时代,当时您必须创建样板代码来打开事务,并且很难管理事务实例(而且您无法确定如何管理事务)。但是,当您使用声明式配置时,情况并没有那么糟。Spring在大多数方法使用Propagation.REQUIRED
事务模式的情况下,提倡约定而非配置样式。在Spring中,当您用@Transactional
装饰方法时,Propagation.REQUIRED
是默认模式(这种传播被硬编码为@Transactional
注释声明),这意味着新的逻辑事务被映射到相同的物理事务,因此用@Transactional
装饰DAO类是无害的有关Spring中事务传播的参考,请参见http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/transaction.html#tx-propagation
在Spring Data JPA中(我很确定他们知道自己在做什么),例如,CRUD methods on repository instances are transactional by default。这在某些情况下可能很有用,这种机制与Hibernate允许您从
Session
获取()一些任意对象来显示而不声明显式事务时的机制相同(当然,这并不意味着框架以某种方式设法不使用事务——在本例中是隐式的)