1. 程式人生 > >SpringMVC事務失效的一種情況-bean載入順序問題

SpringMVC事務失效的一種情況-bean載入順序問題

首先給大家看一個範例java代理的範例:

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();
	}
事務其實就是這麼回事,對於設定了事務的函式而言,其實就是SpringMVC生成一個代理,訪問相應函式,這也就不難解釋某種情況事務失效的原因了
	  <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>  
則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的生成要後於事務的宣告,具體方式有很多種,大家可以任意選擇