Spring注入具体类而不是代理

mih*_*ihn 4 java spring jpa

我有一个问题,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 />
Run Code Online (Sandbox Code Playgroud)

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

Bor*_*hov 5

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

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

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

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

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

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

http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/transaction.html#tx-propagation在春天的事务传播参考

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