日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
Java編程中使用動(dòng)態(tài)代理實(shí)現(xiàn)AOP功能

一、Java編程使用的背景

成都創(chuàng)新互聯(lián)專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于網(wǎng)站設(shè)計(jì)制作、網(wǎng)站建設(shè)、青原網(wǎng)絡(luò)推廣、微信平臺(tái)小程序開(kāi)發(fā)、青原網(wǎng)絡(luò)營(yíng)銷、青原企業(yè)策劃、青原品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠(chéng)為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);成都創(chuàng)新互聯(lián)為所有大學(xué)生創(chuàng)業(yè)者提供青原建站搭建服務(wù),24小時(shí)服務(wù)熱線:18982081108,官方網(wǎng)址:www.cdcxhl.com

也不能算是使用的背景,最多只能算是一個(gè)在什么條件下面我想到了使用動(dòng)態(tài)代理實(shí)現(xiàn)AOP的攔截功能):因?yàn)樵陧?xiàng)目中程序的結(jié)構(gòu)是使用SOAP調(diào)用JNI,因此在SOAP服務(wù)端里面沒(méi)有任何實(shí)現(xiàn)代碼,僅僅是new一個(gè)JNI的對(duì)象,然后調(diào)用JNI對(duì)應(yīng)的方法。但是在調(diào)用JNI方法之前需要對(duì)傳進(jìn)JNI的JavaBean進(jìn)行初始化,而且還需要記錄日志。而SOAP服務(wù)端的代碼是通過(guò)ant自動(dòng)生成的,需要對(duì)他進(jìn)行手工的修改,在修改過(guò)程中發(fā)現(xiàn)每一個(gè)方法里面都是相同的:記錄進(jìn)入方法的日志、初始化JavaBean和記錄退出方法的日志,這寫(xiě)東西都是通過(guò)拷貝粘貼來(lái)完成的,想到如果以后再加一個(gè)什么功能的時(shí)候又得每一個(gè)方法進(jìn)行拷貝粘貼,而且方法的數(shù)量還不少,所以覺(jué)得這樣來(lái)實(shí)現(xiàn)是不科學(xué)的。示例代碼如下:

 
 
 
  1. public class SOAP{ 
  2. private JniInterface jni = null; 
  3. private Log log = 。。。; 
  4. public SOAP(){ 
  5. jni=new JniClass(); 
  6. /**方法A**/ 
  7. public JavaBeanA aMethod(JavaBeanA javaBeanA){ 
  8. log.debug("進(jìn)入A方法"); 
  9. //初始化JavaBean 
  10. Init(javaBeanA); 
  11. //調(diào)用JNI對(duì)應(yīng)的方法 
  12. JavaBeanA result = jni.aMethod(javaBeanA); 
  13. log.debug("退出A方法"); 
  14. return result; 
  15. …………………………………… 
  16. …………………………………… 
  17. 等等,很多這樣的方法 
  18. …………………………………… 
  19. …………………………………… 

從示例代碼里面可以看出,除了調(diào)用JNI對(duì)應(yīng)的方法不同之外,其他的都是相同的代碼,把所有的東西進(jìn)行拷貝復(fù)制是不合理的。每當(dāng)對(duì)SOAP進(jìn)行修改,就必須將所有的方法重新拷貝粘貼。為了省去拷貝粘貼這一工序,所以使用動(dòng)態(tài)代理實(shí)現(xiàn)AOP攔截共能。

二、實(shí)現(xiàn)AOP攔截

1.定義Interceptor接口

 
 
 
  1. public interface Interceptor { 
  2. //在調(diào)用之前調(diào)用該方法 
  3. public void before(InvokeJniInfo invInfo); 
  4. //在調(diào)用之后調(diào)用該方法 
  5. public void after(InvokeJniInfo invInfo); 
  6. //出現(xiàn)異常之后調(diào)用該方法 
  7. public void exceptionThrow(InvokeJniInfo invInfo); 

2. 定義 InvokeJniInfo 類

在Interceptor接口中的InvokeJniInfo類,該類的定義如下:

 
 
 
  1. public class InvokeJniInfo { 
  2. //被代理的對(duì)象 
  3. Object proxy; 
  4. //被調(diào)用的方法 
  5. Method method; 
  6. //被調(diào)用方法的參數(shù)列表 
  7. Object[] args; 
  8. //調(diào)用之后的結(jié)果 
  9. Object result; 
  10. //拋出的異常 
  11. Throwable exception; 
  12. public InvokeJniInfo(Object proxy, 
  13. Method method, 
  14. Object[] args, 
  15. Object result, 
  16. Throwable exception){ 
  17. this.proxy = proxy; 
  18. this.method = method; 
  19. this.args = args; 
  20. this.result = result; 
  21. this.exception = exception; 
  22. ………………………………………………………… 
  23. ………………………………………………………… 

所有成員的get/set方法

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

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

}

從該類的成員變量可以知道,這個(gè)類使用來(lái)將調(diào)用函數(shù)的基本信息如代理的對(duì)象,調(diào)用的方法,調(diào)用方法的參數(shù)等信息傳遞給Interceptor,使得在Interceptor 之中可以通過(guò)使用該對(duì)象作出相應(yīng)的攔截。

3.實(shí)現(xiàn)一個(gè)抽象的攔截器AbstractInterceptor

該攔截器實(shí)現(xiàn)了Interceptor接口,它里面的方法全都是空的,其目的是當(dāng)某些攔截器只是需要實(shí)現(xiàn)三個(gè)方法中的一個(gè)方法或者兩個(gè)方法的時(shí)候,就可以繼承該抽象類,覆蓋需要的實(shí)現(xiàn)的方法就可以了。

4.實(shí)現(xiàn)日志記錄攔截器LogInterceptor

該攔截器主要是實(shí)現(xiàn)在調(diào)用之前記錄日志,調(diào)用之后記錄日志和出現(xiàn)異常的時(shí)候記錄日志。其代碼如下:

 
 
 
  1. public class LogInterceptor implements Interceptor {

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

  3. public void before(InvokeJniInfo invInfo) {

  4. //調(diào)用InvokeJniInfo對(duì)象的Method的getName方法獲取方法名

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

  6. }

  7. public void after(InvokeJniInfo invInfo) {

  8. //調(diào)用InvokeJniInfo對(duì)象的Method的getName方法獲取方法名

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

  10. }

  11. public void exceptionThrow(InvokeJniInfo invInfo) {

  12. //調(diào)用InvokeJniInfo對(duì)象的Method的getName方法獲取方法名

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

  14. //調(diào)用InvokeJniInfo對(duì)象的Exception的getStackTrace方法獲取具體異常并記錄

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

5.實(shí)現(xiàn)初始化JavaBean攔截器InitParamsInterceptor

該類繼承AbstractInterceptor,只需覆蓋before方法即可。其代碼如下:

 
 
 
  1. public class InitParamsInterceptor extends AbstractInterceptor { 
  2. public void before(InvokeJniInfo invInfo) { 
  3. if(invInfo.getArgs().length>0){ 

//初始化***個(gè)參數(shù)

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

6.實(shí)現(xiàn)動(dòng)態(tài)代理處理器InterceptorHandler

該類實(shí)現(xiàn)了java.lang.reflect.InvocationHandler接口。

 
 
 
  1. public class InterceptorHandler implements InvocationHandler {

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

  3. //攔截器列表

  4. private List interceptors = null;

  5. //存放原始對(duì)象

  6. private Object orginalObject;

  7. //使用Proxy返回一個(gè)對(duì)象。注意這里傳進(jìn)去的對(duì)象的對(duì)象必須實(shí)現(xiàn)一個(gè)接口

  8. public Object bind(Object obj) { 
  9. this.orginalObject = obj; 
  10. return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj 
  11. .getClass().getInterfaces(), this); 
  12. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
  13. Object result = null; 
  14. Throwable ex = null; 
  15. InvokeJniInfo invInfo = new InvokeJniInfo(proxy,method,args,result,ex); 
  16. log.debug("Invoking Before Intercepors!"); 

//實(shí)現(xiàn)方法調(diào)用之前進(jìn)行攔截的方法

 
 
 
  1. invokeInterceptorBefor(invInfo); 
  2. try{ 
  3. log.debug("Invoking Proxy Method!"); 
  4. //調(diào)用方法 
  5. result = method.invoke(orginalObject,args); 
  6. invInfo.setResult(result); 
  7. log.debug("Invoking After method!"); 

//實(shí)現(xiàn)方法調(diào)用之后進(jìn)行攔截的方法

 
 
 
  1. invokeInterceptorAfter(invInfo); 
  2. }catch(Throwable tr){ 
  3. invInfo.setException(tr); 
  4. log.error("Invoking exceptionThrow method!"); 

//實(shí)現(xiàn)出現(xiàn)異常進(jìn)行攔截的方法

 
 
 
  1. invokeInterceptorExceptionThrow(invInfo); 
  2. return result; 

//獲取攔截器列表

 
 
 
  1. private synchronized List getIntercetors(){ 
  2. if(null == interceptors){ 
  3. interceptors = new ArrayList(); 

//添加日志記錄攔截器

 
 
 
  1. interceptors.add(new LogInterceptor()); 

//添加初始化JavaBean攔截器

 
 
 
  1. interceptors.add(new InitParamsInterceptor()); 

//如果需要添加其他功能,可以很方便的添加其他的攔截器實(shí)現(xiàn)功能

 
 
 
  1. return interceptors; 
  2. private void invokeInterceptorBefor(InvokeJniInfo invInfo){ 
  3. List interceptors = getIntercetors(); 
  4. int len = interceptors.size(); 

//遍歷所有攔截器,并調(diào)用攔截器的before方法

 
 
 
  1. for(int i = 0;i((Interceptor)interceptors.get(i)).before(invInfo); 
  2. private void invokeInterceptorAfter(InvokeJniInfo invInfo){ 
  3. List interceptors = getIntercetors(); 
  4. int len = interceptors.size(); 

//遍歷所有攔截器,并調(diào)用攔截器的after方法

 
 
 
  1. for(int i = len - 1;i >= 0;i--){ 
  2. ((Interceptor)interceptors.get(i)).after(invInfo); 
  3. private void invokeInterceptorExceptionThrow(InvokeJniInfo invInfo){ 
  4. List interceptors = getIntercetors(); 
  5. int len = interceptors.size(); 

//遍歷所有攔截器,并調(diào)用攔截器的exceptionThrow方法

 
 
 
  1. for(int i = len - 1;i >= 0;i--){ 
  2. ((Interceptor)interceptors.get(i)).exceptionThrow(invInfo); 

7.獲取動(dòng)態(tài)代理對(duì)象工廠InterceptorFactory

 
 
 
  1. public class InterceptorFactory { 
  2. private static Log log = LogFactory.getLog(InterceptorFactory.class); 
  3. public static Object getClassInstance(String clzName) { 
  4. Class cls; 
  5. Object obj = null; 
  6. try { 
  7. cls = Class.forName(clzName); 
  8. obj = (Object) cls.newInstance(); 
  9. } catch (Exception e) { 
  10. log.error(e.getStackTrace()); 
  11. return obj; 
  12. public static Object getInterceptorProxyedObject(String clzName) { 
  13. InterceptorHandler aopHandler = new InterceptorHandler(); 
  14. Object obj = getClassInstance(clzName); 
  15. return aopHandler.bind(obj); 
  16. 8.修改以前的代碼,使用動(dòng)態(tài)代理實(shí)現(xiàn) 
  17. public class SOAP{ 
  18. private JniInterface jni = null; 
  19. private Log log = 。。。; 
  20. public SOAP(){ 
  21. jni=(JniInterface)InterceptorFactory.getInterceptorProxyedObject("JniClass"); 
  22. /**方法A**/ 
  23. public JavaBeanA aMethod(JavaBeanA javaBeanA){ 
  24. return jni.aMethod(javaBeanA); 

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

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

等等,很多這樣的方法

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

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

}

從紅色代碼對(duì)比可以看出,省了很多代碼。

三、總結(jié)

1.必須徹底貫徹針對(duì)接口編成這一編程思想。

2.明白了這個(gè),是不是也明白了Spring的AOP的實(shí)現(xiàn)了?以及為什么要使用Spring的AOP的時(shí)候必須使用他的BeanFactory呢?


網(wǎng)站欄目:Java編程中使用動(dòng)態(tài)代理實(shí)現(xiàn)AOP功能
文章鏈接:http://www.5511xx.com/article/cosocph.html