經過面向接口編程進行日誌輸出由於要使用代理類,就必需要實現固定的接口,具備必定的侷限性。有沒有一種通用的機制,無論是否是實現這個接口,均可以實現日誌信息的輸出?java
Java提供的 InvocationHandler 接口能夠實現這種功能。apache
首先編寫一個日誌信息的代理類,這個代理類實現了接口 InvocationHandler,而後和前面一個實例相似,編寫一個接口並實現這個接口,在實現類中編寫具體的訂票業務代碼,最後針對接口編寫測試代碼。編程
(1)編寫日誌信息的代理類 LogProxy,這個代理類實現了接口 InvocationHandler,能夠對任何接口實現日誌信息的輸出ide
package com.gc.action;測試
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;this
import org.apache.log4j.Level;
import org.apache.log4j.Logger;代理
/*
* 日誌信息的代理類
*/
public class LogProxy implements InvocationHandler{
private Logger logger = Logger.getLogger(this.getClass().getName());
private Object delegate;
//綁定代理對象
public Object bind(Object delegate){
this.delegate = delegate;
return Proxy.newProxyInstance(delegate.getClass().getClassLoader(), delegate.getClass().getInterfaces(), this);
}
//針對接口編程
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
try {
//在方法調用先後進行日誌輸出
logger.log(Level.INFO, args[0] + " 開始訂票");
result = method.invoke(delegate, args);
logger.log(Level.INFO, args[0] + " 訂票結束");
} catch (Exception e) {
logger.log(Level.INFO, e.toString());
}
return result;
}
日誌
}對象
(2)編寫接口 FlyBookInterface接口
package com.gc.impl;
public interface FlyBookInterface {
public void doBook(String name);
}
(3) FlyBookInterface的實現類,其中doBook實現具體的訂票業務代碼
package com.gc.action;
import com.gc.impl.FlyBookInterface;
public class FlyBook implements FlyBookInterface{
@Override
public void doBook(String name) {
// 訂票相關的具體業務代碼
}
}
(4)編寫測試代碼,使用日誌代理類 LogProxy 實現日誌的輸出
package com.gc.action;
import com.gc.impl.FlyBookInterface;
public class TestFlyBook {
public static void main(String[] args) {
//實現了對日誌類的重用
LogProxy logProxy = new LogProxy();
FlyBookInterface flyBookProxy = (FlyBookInterface)logProxy.bind(new FlyBook());
flyBookProxy.doBook("喵喵");
}
}
運行結果:
[INFO ] 2017-01-03 11:47:40 com.gc.action.LogProxy-喵喵 開始訂票 [INFO ] 2017-01-03 11:47:40 com.gc.action.LogProxy-喵喵 訂票結束