今天就跟大家聊聊有关Java中怎么利用动态代理实现AOP功能,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
一、Java编程使用的背景
也不能算是使用的背景,最多只能算是一个在什么条件下面我想到了使用动态代理实现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); }
看完上述内容,你们对Java中怎么利用动态代理实现AOP功能有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。