赛迪网 > IT技术 Java > 技术动态
  IT资讯搜索
 
IT产品搜索
[程序开发][网管世界][网络安全][数据库技术]
[操作系统][嘉宾聊天·在线访谈][活动集锦]
[精彩专题][Symantec专区][订阅IT技术周刊]
[开发论坛][网管论坛][安全论坛][数据库论坛]
[操作系统论坛][Sybase专区][IBM dW技术专区]
[病毒求助][病毒与漏洞播报][文档·源码下载]

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

发布时间:2008.04.09 04:50     来源:赛迪网    作者:店小二

【赛迪网技术报道】

一、使用的背景(也不能算是使用的背景,最多只能算是一个在什么条件下面我想到了使用动态代理实现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().length>0){

//初始化第一个参数

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呢?

(责任编辑:高爽)


[ 发表评论 ] 字体[  ] [ 打印 ] [ 进入博客 ] [ 进入论坛 ]  [ 推荐给朋友 ]
  相关文章
· Java编程语言中创建和使用日期的详细介绍 (04-08) · SE6中调用编译器 (04-08)
· 最容易犯的21种错误 (04-08) · Java进阶:在SE6中调用编译器的两种方法 (04-08)
· 写给程序员:从C++转到Java需注意的地方 (04-07) · 保存Java程序状态及设置Properties文件 (04-07)
· Java进阶:在SE6中调用编译器的两种方法 (04-07) · 使用Java语言编写程序最容易犯的21种错误 (04-07)
· Java基础知识 Java中抽象类和接口的区别 (04-03) · Java基础知识 Java中抽象类和接口的区别 (04-03)
  客户需求反馈表
* 姓  名:
更多资料  了解方案  认识厂商
* 单位名称:
* 联系电话:
* 电子邮件:
  赛迪推荐  
  手机·资费 ·新品·导购·评测·手机资费·宽带
手机搜索  诺基亚 N73 MOTO Z6
  IT产品 ·笔记本·台式机·服务器·打印·投影
IT产品搜索 
  IT技术 ·开发·网管·安全·数据库·操作系统
  信息化 ·热点·专题·访谈·周刊·方案案例
· 信息化市场百家争鸣 SaaS深陷争议“泥潭”
· 提高管理水平 "两栖"CIO应具备的六大能力
· 国产ITIL运维先行者 四大厂商角力BI市场
· 金融行业GSN专题解决方案 企业网解决方案
  IT博客 ·曾剑秋·项立刚·Java学习·网管
  IT技术论坛 ·开发·网管·安全·数据库·系统