Spring + Hibernate如何使用AspectJ来控制事务

时间:2014-04-10 21:35:54

标签: spring hibernate transactions

在代理模式(默认设置)下,只拦截通过代理进入的外部方法调用。这意味着实际上,自调用目标对象中的一个方法调用目标对象的另一个方法,即使被调用的方法用@Transactional标记,也不会在运行时导致实际的事务。 所以我想使用AspectJ,但我无法通过sessionFactory.getCurrentSession()获取会话,这会导致以下异常。 org.hibernate.HibernateException:没有Hibernate会话绑定到线程,配置不允许在这里创建非事务性的

我在运行时添加了VM参数。 -javaagent:/Users/xx/workStation/workspace/SpringHibernate/src/lib/spring-instrument-3.2.8.RELEASE.jar

这是配置文件 aop.xml文件

<aspectj>
<weaver options="-Xset:weaveJavaxPackages=true -showWeaveInfo">
</weaver>

beans.xml

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref = "dataSource"/>
     <property name="mappingResources">
        <list>
            <value>config/User.hbm.xml</value>
        </list>
     </property>
    <property name="hibernateProperties">
        <value>
            hibernate.dialect=org.hibernate.dialect.MySQLDialect
            hibernate.hbm2ddl.auto=update
            hibernate.show_sql=true
            hibernate.format_sql=false
        </value>
    </property>
</bean>

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref = "sessionFactory"/>
    <property name="nestedTransactionAllowed" value = "true"/>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="txManager" />
<context:load-time-weaver />

感谢您的回答。 如果我删除了aop.xml,我收到了一个警告: warning javax.* types are not being woven because the weaver option '-Xset:weaveJavaxPackages=true' has not been specified。 否则我得到了以下信息 [AppClassLoader@546b97fd] weaveinfo Join point 'method-execution(java.util.List com.yonghui.sh.service.impl.UserServiceBean.getUsers())' in Type 'com.yonghui.sh.service.impl.UserServiceBean' (UserServiceBean.java:106) advised by around advice from 'org.springframework.transaction.aspectj.AnnotationTransactionAspect' (AbstractTransactionAspect.aj:59) [AppClassLoader@546b97fd] weaveinfo Join point 'method-execution(void com.yonghui.sh.service.txtest.TxTestB.txC())' in Type 'com.yonghui.sh.service.txtest.TxTestB' (TxTestB.java:32) advised by around advice from 'org.springframework.transaction.aspectj.AnnotationTransactionAspect' (AbstractTransactionAspect.aj:59) 。 我认为课程是编织的。我只是使用JUnit来运行一些不在Web上下文中的测试。

似乎问题是“静态的”。

static UserService userService;
static TxTest txTest;
static TxTestX txTestx;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
    ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
    userService = (UserService)ac.getBean("UserService");
    txTest = (TxTest)ac.getBean("txTestA");
    txTestx = (TxTestX)ac.getBean("txTestX");
}

如果我不使用JUnit,它运作良好。

public class TxTestMain {

public static void main(String[] args) {
    ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
    TxTest txTestA = (TxTest)ac.getBean("txTestA");
    txTestA.txA();
}

}

怎么回事?

1 个答案:

答案 0 :(得分:0)

  

在代理模式(默认设置)下,只有外部方法调用   通过代理进入是截获的。这意味着   自调用,实际上是目标对象调用中的一个方法   目标对象的另一种方法,不会导致实际的   即使调用的方法被标记,运行时的事务也是如此   @Transactional。

我不知道这里是否存在问题但是bean可以通过代理调用自己的方法。只需在您的bean接口(如ApplicationContextAware和BeanNameAware)中实现,并使用这两个,您可以询问有关您实际所在的bean的上下文,并通过代理(在事务中)调用任何方法。这当然只有当范围是SINGLETON时才有效,如果是PROTOTYPE,还有一些方法可以通过API实现。