`
xsuo
  • 浏览: 123525 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

JDK核心API:使用动态代理实现AOP功能

阅读更多
一、使用的背景(也不能算是使用的背景,最多只能算是一个在什么条件下面我想到了使用动态代理实现AOP的拦截功能):

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

<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->  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接口

<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->  public interface Interceptor {   //在调用之前调用该方法   public void before(InvokeJniInfo invInfo);   //在调用之后调用该方法   public void after(InvokeJniInfo invInfo);   //出现异常之后调用该方法   public void exceptionThrow(InvokeJniInfo invInfo);   }

  2. 定义 InvokeJniInfo 类

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

<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->  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

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

<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->  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方法即可。其代码如下:

<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->  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接口。

<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->  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

<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->  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.修改以前的代码,使用动态代理实现
 

<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->  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动态代理(JDK和cglib).pdf

    JDK动态代理基于Java的反射API,它要求被代理的目标对象必须实现一个或多个接口。JDK动态代理的核心类是`java.lang.reflect.Proxy`和`java.lang.reflect.InvocationHandler`。`Proxy`类用于创建动态代理实例,而`...

    springAOP配置动态代理实现

    1. **JDK动态代理**:Spring在没有CGLIB库的情况下,会使用Java的反射API创建动态代理。动态代理类会实现目标接口,并在调用接口方法时插入通知。因此,使用JDK动态代理的目标类必须实现至少一个接口。 2. **CGLIB...

    Java JDK 实现AOP

    以下是一个简单的示例,展示了如何使用Java反射API实现AOP: ```java import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ...

    JAVA JDK1.6 API中文帮助文档

    3. **动态代理**:Java 1.6引入了更强大的动态代理机制,使得在运行时创建代理类成为可能,这对于实现AOP(面向切面编程)和其他设计模式非常有用。 4. **并发编程增强**:加入了`java.util.concurrent`包,提供了...

    [#0x0042] Spring AOP学习(二):动态代理

    本文将深入探讨动态代理在Spring框架中的应用,以及如何通过JDK的动态代理机制实现这一功能。动态代理是面向切面编程(AOP)的一种实现方式,它允许我们在不修改原有代码的情况下,为对象添加额外的功能。 首先,...

    JDK_API_1.6.CHM 中文版

    3. **动态代理**:动态代理允许在运行时创建实现了指定接口的新类,这对于实现AOP(面向切面编程)和其他设计模式非常有用。 4. **增强的I/O和NIO**:JDK 1.6引入了NIO.2,增加了对文件系统操作的支持,如异步I/O、...

    springboot中的 动态代理的选择测试代码

    总结一下,Spring Boot的动态代理主要通过AOP实现,可以使用JDK代理或CGLIB代理,这取决于目标对象是否实现了接口。动态代理使得我们可以在不修改原有业务代码的情况下,灵活地插入额外的功能,提高了代码的可维护性...

    JDK1.8和JDK1.6API帮助文档

    3. **动态代理**:Java.lang.reflect.Proxy支持动态创建代理对象,方便实现回调和AOP(面向切面编程)。 4. **增强的数据库连接(JDBC)**:JDBC API增加了对存储过程的支持,提升了SQL查询的执行效率。 5. **XML...

    jdk动态代理 cglib3.0动态代理

    JDK动态代理基于Java反射API实现,它提供了`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口。`Proxy`类用于创建动态代理实例,而`InvocationHandler`接口则定义了处理方法调用的逻辑。 1....

    JDK6API中文参考手册

    5. **动态代理**:Java 6引入了动态代理,允许在运行时创建代理类,这对于实现AOP(面向切面编程)和事件监听等功能非常有用。 6. **枚举类型**:在JDK6中,枚举成为一种全新的数据类型,它比传统的常量类更安全、...

    JDK_API_1_6

    3. **动态代理**:Java 1.6的动态代理功能使得在运行时创建接口实现类成为可能,这在AOP(面向切面编程)和其他需要动态行为的场景中非常有用。 4. **NIO.2**(New IO 2):引入了新的文件系统API,提供了异步I/O...

    解释Spring中的Aop代理

    - JDK动态代理:基于Java反射API实现,适用于接口代理。如果目标对象实现了至少一个接口,Spring会使用JDK动态代理创建一个代理对象,该代理对象在调用接口方法时插入切面逻辑。 - CGLIB代理:如果目标对象没有...

    JDK 1.6 API中文完整版

    6. **动态代理(Dynamic Proxies)**:`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口提供了创建动态代理对象的能力,用于在运行时创建满足特定接口的新类,常用于AOP(面向切面编程)或...

    42 离开Spring AOP,我们如何实现AOP功能?慕课专栏1

    Spring AOP默认使用JDK动态代理来实现AOP功能。JDK动态代理基于Java反射API,它要求被代理的对象必须实现至少一个接口。如果目标类没有实现接口,或者希望进行更底层的代理(如方法拦截),Spring AOP会使用CGLIB库...

    JDK1.6 API英文版all(CHM)

    4. **动态代理(Dynamic Proxies)**:允许在运行时创建接口的代理实现,常用于AOP(面向切面编程)和事件处理。 5. **NIO.2(New I/O 2)**:增加了文件系统操作,如异步I/O和文件通道,提高了文件操作的效率。 6...

    JDK1.6 API帮助文档.zip

    2. **动态代理类**:Java 1.6引入了`java.lang.reflect.Proxy`类,允许开发者在运行时创建接口的代理实现,用于实现AOP(面向切面编程)或其他动态行为。 3. **改进的并发性**:JDK1.6增强了多线程处理能力,例如`...

    JDK_API_1.6

    JDK 1.6引入了动态代理,允许在运行时创建实现了指定接口的新类。这在实现AOP(面向切面编程)和事件监听器等方面非常有用。 **3. 改进的内存管理** JDK 1.6的垃圾收集器进行了优化,提升了内存管理效率,降低了...

    jdk-api-1.6-English.rar_API1.6 Engli_jdk 6 api en_jdk1.6 api en_

    3. **动态代理**:`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口的引入,使得动态创建代理对象成为可能,便于实现AOP(面向切面编程)。 4. **NIO.2**:JDK 1.6引入了NIO.2,即新的非...

    AOP的实现机制.

    2. 代理创建:Spring根据目标对象是否实现了接口,选择使用JDK动态代理或CGLIB代理。代理类会拦截对目标对象的所有调用。 3. 通知执行:当代理对象的方法被调用时,Spring会检查该方法是否匹配切点表达式。如果匹配...

Global site tag (gtag.js) - Google Analytics