專案中SOAP服務層調用JNI,每個方法都包含相同邏輯:記錄入口日誌、初始化JavaBean、調用JNI、記錄出口日誌。代碼由Ant自動生成,手工修改維護成本極高。引入動態代理實現AOP攔截,將橫切關注點抽離,實現代碼復用與解耦。
public class SOAP {
private JniInterface jni = new JniClass();
private Log log = ...;
public JavaBeanA aMethod(JavaBeanA param) {
log.debug("進入A方法");
init(param); // 重複邏輯1
JavaBeanA result = jni.aMethod(param); // 核心業務
log.debug("退出A方法"); // 重複邏輯2
return result;
}
// 數十個類似方法...
}
public interface Interceptor {
void before(InvokeJniInfo info); // 方法前
void after(InvokeJniInfo info); // 方法後
void exceptionThrow(InvokeJniInfo info); // 異常時
}
public class InvokeJniInfo {
Object proxy; // 代理對象
Method method; // 被調用方法
Object[] args; // 參數列表
Object result; // 返回值
Throwable exception; // 異常信息
// 構造器、getter/setter...
}
public abstract class AbstractInterceptor implements Interceptor {
public void before(InvokeJniInfo info) {}
public void after(InvokeJniInfo info) {}
public void exceptionThrow(InvokeJniInfo info) {}
}
日誌攔截器
public class LogInterceptor implements Interceptor {
private Log log = LogFactory.getLog("init");
public void before(InvokeJniInfo info) {
log.debug("Enter " + info.getMethod().getName());
}
public void after(InvokeJniInfo info) {
log.debug("Exit " + info.getMethod().getName());
}
public void exceptionThrow(InvokeJniInfo info) {
log.error("Error in " + info.getMethod().getName(), info.getException());
}
}
參數初始化攔截器
public class InitParamsInterceptor extends AbstractInterceptor {
public void before(InvokeJniInfo info) {
if (info.getArgs().length > 0) {
InitContainsObjectNullUtil.initContainsOutParameter(info.getArgs()[0]);
}
}
}
public class InterceptorHandler implements InvocationHandler {
private List<Interceptor> interceptors;
private Object target;
public Object bind(Object obj) {
this.target = obj;
return Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
this
);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
InvokeJniInfo info = new InvokeJniInfo(proxy, method, args, null, null);
// 前置攔截
for (Interceptor ic : getInterceptors()) ic.before(info);
try {
Object result = method.invoke(target, args);
info.setResult(result);
// 後置攔截(逆序)
for (int i = interceptors.size()-1; i >= 0; i--)
interceptors.get(i).after(info);
return result;
} catch (Throwable t) {
info.setException(t);
// 異常攔截(逆序)
for (int i = interceptors.size()-1; i >= 0; i--)
interceptors.get(i).exceptionThrow(info);
throw t;
}
}
private synchronized List<Interceptor> getInterceptors() {
if (interceptors == null) {
interceptors = new ArrayList<>();
interceptors.add(new LogInterceptor());
interceptors.add(new InitParamsInterceptor());
// 可動態擴展其他攔截器
}
return interceptors;
}
}
public class InterceptorFactory {
public static Object getInterceptorProxyedObject(String className) {
InterceptorHandler handler = new InterceptorHandler();
Object obj = Class.forName(className).newInstance();
return handler.bind(obj);
}
}
// 重構後的SOAP類
public class SOAP {
private JniInterface jni;
public SOAP() {
jni = (JniInterface) InterceptorFactory.getInterceptorProxyedObject("JniClass");
}
public JavaBeanA aMethod(JavaBeanA param) {
return jni.aMethod(param); // 僅保留核心調用
}
}