通过面向接口编程进行日志输出因为要使用代理类,就必须要实现固定的接口,具有一定的局限性。有没有一种通用的机制,不管是不是实现这个接口,都可以实现日志信息的输出?
Java提供的 InvocationHandler 接口可以实现这种功能。
首先编写一个日志信息的代理类,这个代理类实现了接口 InvocationHandler,然后和前面一个实例类似,编写一个接口并实现这个接口,在实现类中编写具体的订票业务代码,最后针对接口编写测试代码。
(1)编写日志信息的代理类 LogProxy,这个代理类实现了接口 InvocationHandler,可以对任何接口实现日志信息的输出
package com.gc.action;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
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-喵喵 订票结束