SpringMVC事務失效的一種情況-bean載入順序問題
阿新 • • 發佈:2019-02-11
首先給大家看一個範例java代理的範例:
事務其實就是這麼回事,對於設定了事務的函式而言,其實就是SpringMVC生成一個代理,訪問相應函式,這也就不難解釋某種情況事務失效的原因了public class MyInvocationHandler implements InvocationHandler { // 目標物件,也就是我們主要的業務,主要目的要做什麼事 private Object delegate; /** * 和你額外需要做得事情,進行繫結,返回一個全新的物件(寫法,基本上固定的) * * @param delegate * @return */ public Object bind(Object delegate) { this.delegate = delegate; return Proxy.newProxyInstance( this.delegate.getClass().getClassLoader(), this.delegate .getClass().getInterfaces(), this); } /** * 你剛才需要執行的方法,都需要通過該方法進行動態呼叫 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object obj = null; // 執行前置的方法 UserDaoSupport.before(); // 通過反射,執行目標方法,也就是你的主要目的 obj = method.invoke(this.delegate, args); // 執行後置的方法 UserDaoSupport.after(); // 返回值給呼叫者 return obj; } } public class UserDaoSupport { public static void before(){ System.out.println("前置日記:列印、啟動事務等.."); } public static void after(){ System.out.println("後置日記:列印、關閉事務等.."); } public static void other(){ System.out.println("做其他的事.."); } } @Test public void proxyTest() { UserDao userDao = (UserDao) new MyInvocationHandler().bind(new UserDaoImpl()); userDao.insert(); }
則com.leon.web.service包下的所有匹配上述三個方法名的函式都會被事務控制,但是現在就出現了一個問題,就是Spring 配置檔案載入順序問題,SpringMVC載入順序如下:web.xml, *-servlet.xml, applicationContext.xml..... 如果在*-servlet.xml中定義了對applicationContext.xml中bean的ref,自然會往後找,但是如果沒有,就正常的載入順序,如在*-servlet.xml聲明瞭<context:component-scan base-package="..."/>而你期望這裡直接就掃描所有的註解,那麼恭喜你,你的事務就無效了,因為,在事務註冊到Spring容器之前,你已經初始化了所有的bean,獲取該bean就不會通過代理,事務就無從談起了。因此,合理的配置方式是保證需要事務管理的bean的生成要後於事務的宣告,具體方式有很多種,大家可以任意選擇<tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="get*" propagation="REQUIRED" rollback-for="java.lang.Exception" read-only="true"/> <tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="interceptorPointCuts" expression="execution(public * com.leon.web.service..*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="interceptorPointCuts" /> </aop:config>