用 java.lang.reflect.Proxy 制作类似AOP 的方法调用 Log 层
个人认为,java.lang.reflect.Proxy 简直是懒人必备的工具。
如,我负责编写一个分布式系统的一个服务,别的应用要调用我的服务的 RMI接口方法。而多人开发有着一个必然的缺点:每人负责的模块均对外提供接口,但事情往往会因为接口的定义者、实现者、使用者间对接口理解的偏差,而在软件的开发中引出不少麻烦。于是,接口调用日志就有作用了。特别是 RMI Interface 的日志。
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.text.MessageFormat; import java.util.Arrays; import org.apache.log4j.Level; import org.apache.log4j.Logger; /** *Afactoryofmethodinvokeloginterceptor. *logtheinvokeparamandresult. *@param<TargetInterface> */ publicclass InvokeLogProxyFactory<TargetInterface> { publicclass MyInvocationHandler implements InvocationHandler { private Level logLevel; private TargetInterface impl; public MyInvocationHandler(Level logLevel, TargetInterface impl) { this.logLevel = logLevel; this.impl = impl; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { final Logger log = Logger.getLogger( impl.getClass() ); String msg = MessageFormat.format( "Calling method {0}({1})", method.getName(), Arrays.toString( args ) ); log.log( logLevel, msg ); Object returnedResult = null; try { returnedResult = method.invoke( impl, args ); } catch ( InvocationTargetException e ) { String msg1 = MessageFormat.format( "Call method[{0}]: catch exceptions:", method.getName() ); log.log( logLevel, msg1, e.getCause() ); throw e.getCause(); } catch( Throwable e ) { log.error( "Runtime exception:", e ); throw e; } log.log( logLevel, "returned val=" + returnedResult ); return returnedResult; } } @SuppressWarnings("unchecked") public TargetInterface create(TargetInterface impl, Level logLevel) { MyInvocationHandler handler = new MyInvocationHandler( logLevel, impl); Object result = Proxy.newProxyInstance(impl.getClass().getClassLoader(), impl.getClass().getInterfaces(), handler); return (TargetInterface) result; } } |