spring入门 :一个输出日志的实例分析Java的代理机制

1.通用的日志输出方法
a. 原来在程序中编写日志时,都要在每一个业务逻辑方法里编写记录日志的代码:
import org.apache.log4j.Level;
import org.apache.log4j.Logger;

public class TimeBook {

         private Logger logger = Logger.getLogger(this.getClass().getName());         //审核数据的相关程序
         public void doAuditing(String name) {
                  logger.log(Level.INFO, name + " 开始审核数据....");
                  //审核数据的相关程序
                  ……   
                  logger.log(Level.INFO, name + " 审核数据结束....");
         }
}

b. 编写测试程序:
import com.gc.action.TimeBook;
public class TestHelloWorld {
         public static void main(String[] args) {
                   TimeBook timeBook = new TimeBook();
timeBook.doAuditing("张三");
    }
}

c.运行测试程序

在上面的示例中,是把日志信息添加在了具体的业务逻辑中,假如程序中其他的代码都需要日志输出的功能,那么每个程序就都要添加和上面类似的代码。这样,在程序中,就会存在很多类似的日志输出代码,造成了很大的耦合,通过什么方法可以使业务逻辑和输出日志的代码分离呢?通过面向接口编程可以改进这个问题。
2.通过面向接口编程实现日志输出
实现思路是:首先把执行考勤审核的doAuditing()方法提取出来成为接口,然后通过一个实体类来实现这个方法,在这个方法里编写具体的考勤审核的业务逻辑,接着通过一个代理类来进行日志输出,最后编写测试程序,查看输出结果。具体步骤如下:
a .接口TimeBookInterface:
import org.apache.log4j.Level;

//通过面向接口编程实现日志输出
public interface TimeBookInterface {
         public void doAuditing(String name);
}

b .实现接口TimeBookInterface:
public class TimeBook implements TimeBookInterface {

public void doAuditing(String name) {
//审核数据的相关程序
……   
}
}

c. 编写一个代理类:
import org.apache.log4j.Level;
import org.apache.log4j.Logger;

public class TimeBookProxy {
private Logger logger = Logger.getLogger(this.getClass().getName());
private TimeBookInterface 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 + " 审核数据结束....");
          }
}

d .编写测试:
public class TestHelloWorld {
         public static void main(String[ ] args) {
           //这里针对接口进行编程
TimeBookProxy timeBookProxy  = new TimeBookProxy(new TimeBook());
timeBookProxy .doAuditing("张三");

    }
}

e.运行测试:

和前面一个日志输出做对比,可以看到,在这个示例中,具体负责考勤审核的业务逻辑代码和日志信息的代码分离开了,并且以后只要实现了接口 TimeBookInterface的类,都可以通过代理类TimeBookProxy实现日志信息的输出,而不用再每个类里面都写日志信息输出的代码,从而实现了日志信息的代码重用
3.使用Java的代理机制进行日志输出
Java提供的InvocationHandler接口可以实现这种功能,首先编写一个日志信息的代理类,这个代理类实现了接口 InvocationHandler,然后和前面一个实例类似,编写一个接口,并实现这个接口,在实现类中编写具体的考勤审核代码,最后针对接口编写测试类,查看测试结果。具体步骤如下:
a .编写一个日志信息的代理类:
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;

//代理类实现了接口InvocationHandler

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);
    }
    //针对接口编程
    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;
    }
}

b .接口TimeBookInterface:
import org.apache.log4j.Level;

//针对接口编程

public interface TimeBookInterface {

         public void doAuditing(String name);

}

c .实现接口:
import com.gc.impl.TimeBookInterface;
public class TimeBook implements TimeBookInterface {
public void doAuditing(String name) {
//审核数据的相关程序
……   
}
}

d .测试代码:
public class TestHelloWorld {
         public static void main(String[ ] args) {
           //实现了对日志类的重用
           LogProxy logProxy  = new LogProxy();
TimeBookInterface timeBookProxy = (TimeBookInterface)logProxy.bind(new TimeBook());
timeBookProxy.doAuditing("张三");
    }
}

e .运行测试:

这种方式,对于其他的类也同样适用,这样就真正地实现了业务逻辑和输出日志信息代码的分离。

你可能感兴趣的:(java,apache,spring,编程,log4j)