Spring的AOP是建立在Java的动态代理的基础上的,学习Java动态代理机制有助于循序渐进地理解AOP的思想。
传统的日志输出方法是在每一个业务逻辑方法里编写记录日志的代码,这样,程序中就会有很多类似的日志输出代码,造成了很大的耦合。那么,使用什么方法可以使业务逻辑和输出日志的代码分离,并实现日志信息代码的重用呢?Java的代理机制可以改善这个问题。
首先编写一个日志信息的代理类,这个类实现了接口InvocationHandler,然后编写一个接口,并实现这个接口,在实现类中编写具体的逻辑代码,最后针对接口编写测试类,查看测试结果。具体步骤如下:
(1)编写一个日志信息的代理类LogProxy,这个类实现了接口InvocationHandler,可以对任何接口实现日志的输出。LogProxy.java代码如下
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
*
*/
package com.jp.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;
/**
* @author JP
*
*/
// 代理类实现了接口InvocationHandler
public class LogProxy implements InvocationHandler {
/*
* (non-Javadoc)
*
* @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
* java.lang.reflect.Method, java.lang.Object[])
*/
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 {
// TODO Auto-generated method stub
Object result = null ;
try {
logger.log(Level.INFO, args[ 0 ] + " 开始审核数据... " );
result = method.invoke(delegate, args);
logger.log(Level.INFO, args[ 0 ] + " 审核数据结束 " );
} catch (Exception e) {
// TODO Auto-generated catch block
logger.log(Level.INFO, e.toString());
}
return result;
}
}
(2)定义一个接口:TimeBookInterface.java
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
/**
* @author JP
*
*/
public interface TimeBookInterface {
public void doAuditing(String name);
}
(3)TimeBook类实现上述接口,doAuditing()方法是具体的业务逻辑处理
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
import org.apache.log4j.Logger;
import com.jp.impl.TimeBookInterface;
/**
* @author JP
*
*/
public class TimeBook implements TimeBookInterface{
private Logger logger = Logger.getLogger( this .getClass().getName());
@Override
public void doAuditing(String name){
System.out.println(name + " is doing something about auditing... " );
}
}
(4)编写测试程序TestHelloWorld.java 使用日志代理类LogProxy实现日志的输出。TestHelloWorld.java代码如下
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
import com.jp.action.LogProxy;
import com.jp.action.TimeBook;
import com.jp.impl.TimeBookInterface;
public class TestHelloWorld {
public static void main(String[] args){
// TODO Auto-generated method stub
LogProxy logProxy = new LogProxy();
TimeBookInterface timeBookProxy = (TimeBookInterface) logProxy.bind( new TimeBook());
timeBookProxy.doAuditing( " 张三 " );
}
}
(5)运行测试程序,即可得到通过LogProxy类输出的日志信息
这种方式,对于其他的类也同样适用,这样就真正实现了业务逻辑和输出日志信息代码的分离