Aop应用原理 JDK动态代理、代理模式与反射

    技术2022-05-19  27

    现在有数学计算的接口和类

    ArithmeticCaculator 接口:

    package com.apress.springrecipes.aop;

    public interface ArithmeticCaculator { public double add(double a,double b); public double sub(double a,double b); public double mul(double a,double b); public double div(double a,double b);}

    ArithmeticCalculatorImpl 实现类:package com.apress.springrecipes.aop;

    public class ArithmeticCalculatorImpl implements ArithmeticCaculator {

     @Override public double add(double a, double b) {  // TODO Auto-generated method stub  double result = a + b;  return result; }

     @Override public double sub(double a, double b) {  // TODO Auto-generated method stub  double result = a - b;  return result; }

     @Override public double mul(double a, double b) {  // TODO Auto-generated method stub  double result = a * b;  return result; }

     @Override public double div(double a, double b) {  // TODO Auto-generated method stub  double result = a / b;  return result; }

    }

     

    在调用接口进行简单数学运算时(加减乘除),需要对每个方法进行日志记录或者针对参数进行有效性验证时,有没有有效的统一的代码呢?

     

    一般在实现类里给各个方法单独编写日志或验证函数的方式为非模块化的方式,导致了代码混乱和分散,我们希望能找到一种模块化的方法。

     

    设计模式:

    应用代理模式,对对象进行包装代理,用该代理对象替换原始对象,任何对原始对象的调用都要先经过代理对象

    动态代理:

    JDK1.3提供动态代理对象支持,能为任意对象创建动态代理,但被代理对象必须至少实现一个接口,并且只有调用申明在接口里的方法才会经过代理

    JDK动态代理需要一个调用处理程序(InvocationHandler)来处理方法的调用,调用处理程序需要实现一个简单的接口

    package java.lang.reflect;

    public interface InvocationHandler{

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

    }

    第一个参数是代理实例,正在调用的是它的方法;第二个参数是类型java.lang.reflect.Method的方法对象,它代表当前正被调用的方法;最后一个参数是被调用的目标方法的参数数组。最后,作为当前方法调用的结果,必须返回一个值。

     

    通过实现InvocationHandler接口,可以编写一个记录方法起始和结束的调用处理程序,我们还需要一个目标计算器对象来执行实际的计算,将它作为构造器参数传入

     

    package com.apress.springrecipes.aop;

    import java.lang.reflect.InvocationHandler;

    import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.util.Arrays;

    import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;

     

    public class CalculatorLoggingProxy implements InvocationHandler {  private Object target;  public CalculatorLoggingProxy(Object target){  this.target = target;//目标计算器对象 }  private Log log = LogFactory.getLog(this.getClass());  @Override public Object invoke(Object proxy/*代理实例*/, Method method/*正被调用的方法*/, Object[] args/*被调用方法的参数*/)   throws Throwable {  // TODO Auto-generated method stub  log.info("The method " + method.getName() + "() begins with " + Arrays.toString(args));  Object result /*方法返回结果*/= method.invoke(target, args);  log.info("The method " + method.getName() + "() ends with " + result);  return result; } public static Object createProxy(Object target){  return Proxy.newProxyInstance(    target.getClass().getClassLoader(), //类加载器,大部分情况下都是被代理对象的类加载器,负责注册代理    target.getClass().getInterfaces()//被代理对象实现的接口  ArithmeticCaculator

        , new CalculatorLoggingProxy(target)//处理方法调用的调用处理程序    ); } public static void main(String[] args){  ArithmeticCaculator arithCal = new ArithmeticCalculatorImpl();//目标计算器对象  ArithmeticCaculator calculatorAop = (ArithmeticCaculator)CalculatorLoggingProxy.createProxy(arithCal);//代理对象  calculatorAop.add(2, 3);//通过代理对象调用目标计算其对象的方法  calculatorAop.div(2, 4); }}

     


    最新回复(0)