(0)准备工作
本文使用log4j日志工具实现日志输出,添加log4j的步骤如下:
(1)下载地址:http://logging.apache.org/log4j/1.2/download.html,下载 【log4j-1.2.17.zip】
(2)将 【log4j-1.2.17.jar】 文件,复制到 lib 下
(3)然后右击添加到资源文件。
(一)通用的日志输出方法
通用的日志输出方法即是在每个业务逻辑方法中,都编写记录日志的代码。
- (1)在每个业务逻辑方法中添加日志记录代码
- (2)测试功能
//****************TimeBook.java*******************
//在业务逻辑中使用log4j作为日志输出的工具
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
public class TimeBook {
private Logger logger = Logger.getLogger(this.getClass().getName());
//doAuditing()方法用来处理实际业务中的考勤审核
//参数name,用来传入是谁执行了类TimeBook中的doAuditing()方法
public void doAuditing(String name) {
logger.log(Level.INFO, name + " 开始审核数据...");
// 审核数据的相关程序
logger.log(Level.INFO, name + " 审核数据结束...");
}
}
//****************TestHelloWorld.java******************
import com.gc.action.TimeBook;
public class TestHelloWorld {
public static void main(String[] args){
TimeBook timeBook = new TimeBook();
timeBook.doAuditing("张三");
}
}
结果
[ INFO ] 2020-04-19 21:42:44 [main] com.gc.action.TimeBook - 张三 开始审核数据...
[ INFO ] 2020-04-19 21:42:44 [main] com.gc.action.TimeBook - 张三 审核数据结束...
使用这种方法,假如程序中其他的代码都需要日志输出功能,则都需要添加上述代码,造成很大耦合。我们可以通过面向接口编程来解决这个问题。
(二)面向接口编程的日志输出方法
- (1)将doAuditing()方法提取出来成为接口 TimeBookInterface
- (2)通过TimeBook实现该接口,并编写具体的审核业务逻辑
- (3)设置一个代理类进行日志输出
- (4)测试
//*****************TimeBookInterface.java*******************
public interface TimeBookInterface {
public void doAuditing(String name);
}
//****************TimeBookInterface.java**********************
public class TimeBook implements TimeBookInterface{
//doAuditing()方法用来处理实际业务中的考勤审核
//参数name,用来传入是谁执行了类TimeBook中的doAuditing()方法
public void doAuditing(String name) {
// 审核数据的相关程序
}
}
//****************TimeBookProxy.java********************
//代理程序
public class TimeBookProxy {
private Logger logger = Logger.getLogger(this.getClass().getName());
private TimeBookInterface timeBookInterface; //定义一个接口对象
public TimeBookProxy(TimeBookInterface timeBookInterface) {
this.timeBookInterface = timeBookInterface; //使接口指向子对象
}
//实际业务处理
public void doAuditing(String name) {
logger.log(Level.INFO, name + " 开始审核数据...");
timeBookInterface.doAuditing(name); //调用子对象的方法
logger.log(Level.INFO, name + " 审核数据结束...");
}
}
//**************TestHelloWorld.java******************
public class TestHelloWorld {
public static void main(String[] args){
TimeBookProxy timeBookProxy = new TimeBookProxy(new TimeBook());
timeBookProxy.doAuditing("张三");
}
}
结果
[ INFO ] 2020-04-19 23:31:47 [main] com.gc.action.TimeBookProxy - 张三 开始审核数据...
[ INFO ] 2020-04-19 23:31:47 [main] com.gc.action.TimeBookProxy - 张三 审核数据结束...
该方法使用代理类实现日志的输出,实现了日志代码的重用性。但是仍具有局限性,因为要使用代理类就必须实现固定的接口。而 Java代理机制具有通用性,不管是不是实现这个接口,都可以实现日志的输出。
(三)使用Java代理机制的日志输出方法
- (1)编写一个接口TimeBookInterface
- (2)用TimeBook实现TimeBookInterface接口,并实现具体审核代码
- (3)编写一个代理类LogProxy实现 InvocationHandler
- (4)测试
//*****************TimeBookInterface.java*******************
public interface TimeBookInterface {
public void doAuditing(String name);
}
//****************TimeBookInterface.java**********************
public class TimeBook implements TimeBookInterface{
//doAuditing()方法用来处理实际业务中的考勤审核
//参数name,用来传入是谁执行了类TimeBook中的doAuditing()方法
public void doAuditing(String name) {
// 审核数据的相关程序
}
}
//****************LogProxy.java**********************
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;
}
}
//***************TestHelloWorld.java********************
public class TestHelloWorld {
public static void main(String[] args){
LogProxy logProxy = new LogProxy();
TimeBookInterface timeBookProxy = (TimeBookInterface)logProxy.bind(new TimeBook());
timeBookProxy.doAuditing("张三");
}
}
结果
[ INFO ] 2020-04-20 00:09:48 [main] com.gc.action.LogProxy - 张三 开始审核数据...
张三
[ INFO ] 2020-04-20 00:09:48 [main] com.gc.action.LogProxy - 张三 审核数据结束...
输出结果的第二行,张三是通过代理类 LogProxy.java 中的 result = method.invoke(delegate, args); 去调用 doAufiting() 函数。通过Java代理机制,真正的实现了业务逻辑和输出日志信息代码的分离。
总结
- 通用的方式:需要在每个类里都增加对输出日志信息的代码。
- 面向接口编程:实现了业务逻辑与输出日志信息代码的分类,但必须依赖固定的接口。
- Java代理机制:真正实现了日志信息代码的重用,且不依赖于固定接口。
扫描二维码关注公众号,回复:
11037422 查看本文章