Java编程应用:使用动态代理实现AOP功能

2016-02-19 20:57 42 1 收藏

人生本是一个不断学习的过程,在这个过程中,图老师就是你们的好帮手,下面分享的Java编程应用:使用动态代理实现AOP功能懂设计的网友们快点来了解吧!

【 tulaoshi.com - 编程语言 】

一、使用的背景(也不能算是使用的背景,最多只能算是一个在什么条件下面我想到了使用动态代理实现AOP的拦截功能):因为在项目中程序的结构是使用SOAP调用JNI,因此在SOAP服务端里面没有任何实现代码,仅仅是new一个JNI的对象,然后调用JNI对应的方法。但是在调用JNI方法之前需要对传进JNI的JavaBean进行初始化,而且还需要记录日志。而SOAP服务端的代码是通过ant自动生成的,需要对他进行手工的修改,在修改过程中发现每一个方法里面都是相同的:记录进入方法的日志、初始化JavaBean和记录退出方法的日志,这写东西都是通过拷贝粘贴来完成的,想到如果以后再加一个什么功能的时候又得每一个方法进行拷贝粘贴,而且方法的数量还不少,所以觉得这样来实现是不科学的。示例代码如下:

public class SOAP{

private JniInterface jni = null;

private Log log = 。。。;

public SOAP(){

jni=new JniClass();

}

/**方法A**/

public JavaBeanA aMethod(JavaBeanA javaBeanA){

log.debug("进入A方法");

//初始化JavaBean

Init(javaBeanA);

//调用JNI对应的方法

JavaBeanA result = jni.aMethod(javaBeanA);

log.debug("退出A方法");

return result;

}

……………………………………

……………………………………

等等,很多这样的方法

……………………………………

……………………………………

}

从示例代码里面可以看出,除了调用JNI对应的方法不同之外,其他的都是相同的代码,把所有的东西进行拷贝复制是不合理的。每当对SOAP进行修改,就必须将所有的方法重新拷贝粘贴。为了省去拷贝粘贴这一工序,所以使用动态代理实现AOP拦截共能。

二、实现AOP拦截

1.定义Interceptor接口

public interface Interceptor {

//在调用之前调用该方法

public void before(InvokeJniInfo invInfo);

//在调用之后调用该方法

public void after(InvokeJniInfo invInfo);

//出现异常之后调用该方法

public void exceptionThrow(InvokeJniInfo invInfo);

}

2. 定义 InvokeJniInfo 类

在Interceptor接口中的InvokeJniInfo类,该类的定义如下:

public class InvokeJniInfo {

//被代理的对象

Object proxy;

//被调用的方法

Method method;

//被调用方法的参数列表

Object[] args;

//调用之后的结果

Object result;

//抛出的异常

Throwable exception;

public InvokeJniInfo(Object proxy,

Method method,

Object[] args,

Object result,

Throwable exception){

this.proxy = proxy;

this.method = method;

this.args = args;

this.result = result;

this.exception = exception;

}

…………………………………………………………

…………………………………………………………

所有成员的get/set方法

…………………………………………………………

…………………………………………………………

}

从该类的成员变量可以知道,这个类使用来将调用函数的基本信息如代理的对象,调用的方法,调用方法的参数等信息传递给Interceptor,使得在Interceptor 之中可以通过使用该对象作出相应的拦截。

3.实现一个抽象的拦截器AbstractInterceptor

该拦截器实现了Interceptor接口,它里面的方法全都是空的,其目的是当某些拦截器只是需要实现三个方法中的一个方法或者两个方法的时候,就可以继承该抽象类,覆盖需要的实现的方法就可以了。

4.实现日志记录拦截器LogInterceptor

该拦截器主要是实现在调用之前记录日志,调用之后记录日志和出现异常的时候记录日志。其代码如下:

public class LogInterceptor implements Interceptor {

private Log log = LogFactory.getLog(“初始化Log” );

public void before(InvokeJniInfo invInfo) {

//调用InvokeJniInfo对象的Method的getName方法获取方法名

log.debug("Enter the" + invInfo.getMethod().getName());

}

public void after(InvokeJniInfo invInfo) {

//调用InvokeJniInfo对象的Method的getName方法获取方法名

log.debug("Exit the" + invInfo.getMethod().getName());

}

public void exceptionThrow(InvokeJniInfo invInfo) {

//调用InvokeJniInfo对象的Method的getName方法获取方法名

log.error("Call the" + invInfo.getMethod().getName() + " has error!");

//调用InvokeJniInfo对象的Exception的getStackTrace方法获取具体异常并记录

log.error(invInfo.getException().getStackTrace());

}

}

5.实现初始化JavaBean拦截器InitParamsInterceptor

该类继承AbstractInterceptor,只需覆盖before方法即可。其代码如下:

public class InitParamsInterceptor extends AbstractInterceptor {

public void before(InvokeJniInfo invInfo) {

if(invInfo.getArgs().length0){

//初始化第一个参数

InitContainsObjectNullUtil.initContainsOutParameter(invInfo.getArgs()[0]);

}

}

}

6.实现动态代理处理器InterceptorHandler

该类实现了java.lang.reflect.InvocationHandler接口。

public class InterceptorHandler implements InvocationHandler {

private static Log log = LogFactory.getLog(InterceptorHandler.class);

//拦截器列表

private List interceptors = null;

//存放原始对象

private Object orginalObject;

//使用Proxy返回一个对象。注意这里传进去的对象的对象必须实现一个接口

public Object bind(Object obj) {

this.orginalObject = obj;

return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj

.getClass().getInterfaces(), this);

}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

Object result = null;

Throwable ex = null;

InvokeJniInfo invInfo = new InvokeJniInfo(proxy,method,args,result,ex);

log.debug("Invoking Before Intercepors!");

//实现方法调用之前进行拦截的方法

invokeInterceptorBefor(invInfo);

try{

log.debug("Invoking Proxy Method!");

//调用方法

result = method.invoke(orginalObject,args);

invInfo.setResult(result);

log.debug("Invoking After method!");

//实现方法调用之后进行拦截的方法

invokeInterceptorAfter(invInfo);

}catch(Throwable tr){

invInfo.setException(tr);

log.error("Invoking exceptionThrow method!");

//实现出现异常进行拦截的方法

invokeInterceptorExceptionThrow(invInfo);

}

return result;

}

//获取拦截器列表

private synchronized List getIntercetors(){

if(null == interceptors){

interceptors = new ArrayList();

//添加日志记录拦截器

interceptors.add(new LogInterceptor());

//添加初始化JavaBean拦截器

interceptors.add(new InitParamsInterceptor());

//如果需要添加其他功能,可以很方便的添加其他的拦截器实现功能

}

return interceptors;

}

private void invokeInterceptorBefor(InvokeJniInfo invInfo){

List interceptors = getIntercetors();

int len = interceptors.size();

//遍历所有拦截器,并调用拦截器的before方法

for(int i = 0;i((Interceptor)interceptors.get(i)).before(invInfo);

}

}

private void invokeInterceptorAfter(InvokeJniInfo invInfo){

List interceptors = getIntercetors();

int len = interceptors.size();

//遍历所有拦截器,并调用拦截器的after方法

for(int i = len - 1;i = 0;i--){

((Interceptor)interceptors.get(i)).after(invInfo);

}

}

private void invokeInterceptorExceptionThrow(InvokeJniInfo invInfo){

List interceptors = getIntercetors();

int len = interceptors.size();

//遍历所有拦截器,并调用拦截器的exceptionThrow方法

for(int i = len - 1;i = 0;i--){

((Interceptor)interceptors.get(i)).exceptionThrow(invInfo);

}

}

}

7.获取动态代理对象工厂InterceptorFactory

public class InterceptorFactory {

private static Log log = LogFactory.getLog(InterceptorFactory.class);

public static Object getClassInstance(String clzName) {

Class cls;

Object obj = null;

try {

cls = Class.forName(clzName);

obj = (Object) cls.newInstance();

} catch (Exception e) {

log.error(e.getStackTrace());

}

return obj;

}

public static Object getInterceptorProxyedObject(String clzName) {

InterceptorHandler aopHandler = new InterceptorHandler();

Object obj = getClassInstance(clzName);

return aopHandler.bind(obj);

}

}

8.修改以前的代码,使用动态代理实现

public class SOAP{

private JniInterface jni = null;

private Log log = 。。。;

public SOAP(){

jni=(JniInterface)InterceptorFactory.getInterceptorProxyedObject("JniClass");

}

/**方法A**/

public JavaBeanA aMethod(JavaBeanA javaBeanA){

return jni.aMethod(javaBeanA);

}

……………………………………

……………………………………

等等,很多这样的方法

……………………………………

……………………………………

}

从红色代码对比可以看出,省了很多代码。

三、总结

1.必须彻底贯彻针对接口编成这一编程思想。

2.明白了这个,是不是也明白了Spring的AOP的实现了?以及为什么要使用Spring的AOP的时候必须使用他的BeanFactory呢?

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

来源:http://www.tulaoshi.com/n/20160219/1624891.html

延伸阅读
一、代理模式 代理模式是常用的java设计模式,特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。 代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提...
?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />   摘要:你想写出无需改变源代码就可以进行扩展的程序吗?这篇文章介绍了如何使用interface和动态class载入来创建高扩展性的系统。从中你也可以学习到如何令其他的编程者和用户不需你的源代码,就可以对程序进行扩展。首先我们看一个没有使用inter...
标签: Web开发
一、 摘要 本文简单阐述了 Proxy 模式及具体说明了如何在 PHP4 中实现动态代理,本文只是给出了一个实现的方法的原型。由于水平有限,有任何意见和建议请反馈给 Binzy [ Binzy at JustDN dot Com ]。 二、 概述 在我们开始实现 Dynamic Proxy 之前,也许我们应该先了解一下什么是 Proxy 和它有什么用。下面是一篇来自博客堂...
标签: PHP
作者:Binzy 来源:超越PHP 一、 摘要 本文简单阐述了Proxy模式及具体说明了如何在PHP4中实现动态代理, 本文只是给出了一个实现的方法的原型. 由于水平有限, 有任何意见和建议请反馈给Binzy [ Binzy at JustDN dot Com ]. 二、 概述 在我们开始实现Dynamic Proxy之前, 也许我们应该先了解一下什么是Proxy和它有什么用. 下面是一...
对于BDE会话期对象来说,BDE别名特别重要,许多方法都需要传递一个数据库的别名作为参数。TSession提供了管理BDE别名的功能。 但是作者往往等到要发布程序时才发现,你的程序由于找不到别名而无法运行,必须在一台已经装了BDE管理程序的机上才能用,你一定非常失望。不要紧,只要在程序中加入以下语句,你的程序就又可以执行。 A...

经验教程

239

收藏

61
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部