所謂的業(yè)務(wù)方法調(diào)用攔截就是業(yè)務(wù)方法在調(diào)用前或后我們可以插入自己的業(yè)務(wù)代碼進(jìn)行攔截處理,如果我們需要在操作人員在操作我們的業(yè)務(wù)模塊時(shí),記錄操作人員的操作日志,那么就可以通過(guò)該功能實(shí)現(xiàn)。在BDF2當(dāng)中,我們通過(guò)Spring的AOP方法攔截提供了名為IMethodInterceptor接口,開(kāi)發(fā)人員可以通過(guò)實(shí)現(xiàn)該接口將其配置到Spring當(dāng)中即可,IMethodInterceptor接口源碼如下:
IMethodInterceptor接口源碼
package com.bstek.bdf2.core.aop;
import java.lang.reflect.Method;
/**
* 實(shí)現(xiàn)該接口用于攔截用戶感興趣的業(yè)務(wù)方法調(diào)用,比如作業(yè)務(wù)操作審計(jì)等
* @author Jacky.gao
* @since 2013年7月11日
*/
public interface IMethodInterceptor {
/**
* 是否支持當(dāng)前方法調(diào)用
* @param objectClass 調(diào)用類class
* @param method 調(diào)用的方法對(duì)象
* @return true表示支持,false表示不支持
*/
boolean support(Class<?> objectClass,Method method);
/**
* 在方法調(diào)用之前攔截,如不需要保持實(shí)現(xiàn)類中該方法為空即可
* @param objectClass 調(diào)用類class
* @param method 調(diào)用的方法對(duì)象
* @param arguments 方法調(diào)用時(shí)采用的參數(shù)集合
* @throws Exception
*/
void doBefore(Class<?> objectClass,Method method,Object[] arguments) throws Exception;
/**
* 在方法調(diào)用之后攔截,如不需要保持實(shí)現(xiàn)類中該方法為空即可
* @param objectClass 調(diào)用類class
* @param method 調(diào)用的方法對(duì)象
* @param arguments 方法調(diào)用時(shí)采用的參數(shù)集合
* @param returnValue 方法調(diào)用完成后的返回值
* @throws Exception
*/
void doAfter(Class<?> objectClass,Method method,Object[] arguments,Object returnValue) throws
Exception;
}
需要注意的是,在使用IMethodInterceptor接口時(shí),我們還需要定義bdf2.globalMethodIntercetporBeanNamesPattern屬性,通過(guò)該屬性來(lái)決定我們AOP實(shí)現(xiàn)要攔截哪些bean的方法調(diào)用,如果不定義該屬性,那么默認(rèn)將不攔截任何bean的方法調(diào)用,比如我們可以在
dorado-home/configure.properties文件當(dāng)中將bdf2.globalMethodIntercetporBeanNamesPattern屬性值設(shè)置為"*Maintain,*Dao",那么就表示將攔截所有bean的id以Maintain結(jié)尾的或以Dao結(jié)尾的bean的方法調(diào)用??梢钥吹皆谶@個(gè)屬性值定義時(shí)多個(gè)值需要用逗號(hào)分隔。
下圖當(dāng)中我將在dorado-home/configure.properties文件當(dāng)中將bdf2.globalMethodIntercetporBeanNamesPattern屬性值設(shè)置為"*Maintain,*Dao":
同時(shí)我們編寫了一個(gè)名為TestMethodInterceptor的IMethodInterceptor接口實(shí)現(xiàn)類,其源碼如下:
TestMethodInterceptor源碼
package test;
import java.lang.reflect.Method;
import org.springframework.stereotype.Component;
import com.bstek.bdf2.core.aop.IMethodInterceptor;
import com.bstek.bdf2.core.context.ContextHolder;
import com.bstek.bdf2.core.view.user.UserMaintain;
@Component
public class TestMethodInterceptor implements IMethodInterceptor {
public boolean support(Class<?> objectClass, Method method) {
if(objectClass.getName().equals(UserMaintain.class.getName())){
return true;
}
return false;
}
public void doBefore(Class<?> objectClass, Method method, Object[] arguments)
throws Exception {
System.out.println("......before invoke:"+method.getName());
System.out.println("......login user:"+ContextHolder.getLoginUserName());
}
public void doAfter(Class<?> objectClass, Method method,
Object[] arguments, Object returnValue) throws Exception {
System.out.println("......after invoke:"+method.getName());
System.out.println("......return value:"+returnValue);
System.out.println("......arguments:"+arguments);
}
}
啟動(dòng)服務(wù),登錄后訪問(wèn)BDF2當(dāng)中的用戶維護(hù)界面,可以看到控制臺(tái)輸出的相關(guān)攔截信息。
注意事項(xiàng)
設(shè)置bdf2.globalMethodIntercetporBeanNamesPattern屬性值,就是在決定應(yīng)該攔截哪些springbean的方法調(diào)用。在我們的Spring環(huán)境當(dāng)中,有各種類型的Bean存在,對(duì)于我們這里的bean方法調(diào)用攔截功能來(lái)說(shuō),要求可以攔截的bean一定要有一個(gè)空的構(gòu)造方法,如果我們?cè)O(shè)置的bdf2.globalMethodIntercetporBeanNamesPattern屬性值,與Spring當(dāng)中一個(gè)沒(méi)有空構(gòu)造方法的Bean匹配,那么就會(huì)出現(xiàn)下面的異常:
java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
這個(gè)異常就是在提示我們當(dāng)前攔截到的Spring bean沒(méi)有空的構(gòu)造方法,所以拋出這么一個(gè)異常。我們當(dāng)前提供攔截操作基于CGLib代理實(shí)現(xiàn),所以也進(jìn)一步說(shuō)明CGLib 代理實(shí)現(xiàn)調(diào)用攔截,要求匹配的Bean一定要有一個(gè)空的構(gòu)造方法。
在BDF2當(dāng)中,提供的與頁(yè)面操作相關(guān)的bean皆以Maintain結(jié)尾,所以在設(shè)置bdf2.globalMethodIntercetporBeanNamesPattern屬性值的時(shí)候只要包含"*Maintain"就可以攔截所有BDF2當(dāng)中頁(yè)面交互操作產(chǎn)生的方法調(diào)用。同時(shí)我們也建議您在業(yè)務(wù)模塊開(kāi)發(fā)時(shí),與前臺(tái)交互的Bean的id在命名是以Maintain結(jié)尾,比如UserMaintain,這就是一個(gè)用戶維護(hù)的bean。
如果您不愿采用Maintain結(jié)尾,我們也強(qiáng)烈建議您采用一個(gè)固定字符串作為bean的id結(jié)尾,比如BO,用于用戶維護(hù)操作的bean相應(yīng)就是UserBO。一旦采用這種原則我們就可以將bdf2.globalMethodIntercetporBeanNamesPattern屬性值設(shè)置為"*Maintain,*BO",這樣既可以攔截BDF2當(dāng)中所有頁(yè)面操作方法調(diào)用,也可以攔截我們業(yè)務(wù)模塊頁(yè)面當(dāng)中的方法調(diào)用。
更多建議: