使用动态代理解决方法调用前后添加日志信息

  一般情况,在每个调用的方法中直接添加日志信息,存在如下问题:

1.代码混乱:越来越多的非业务需求加入(如日志和验证等)后,原有的业务方法急剧膨胀,每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点;

2.代码分散:以日志需求为例,只是为了满足这个单一的需求,就不得不在多个模块里多次重复相同的日志代码,如果日志需求发生变化,必须修改所有的模块。

针对以上问题,使用动态代理带解决。

代理设计模式的原理:使用一个代理将对象包装起来,然后用该代理取代原始对象。任何原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。

1.先定义一个接口

public interface Calc {
    int add(int i,int j);
    int sub(int i,int j);
    int multi(int i,int j);
    int div(int i,int j);

}

2.定义一个接口的实现类,如

public class CalcImpl implements Calc{

    public int add(int i, int j) {
        int result =i+j;
        return result;
    }

    public int sub(int i, int j) {
        int result =i-j;
        return result;
    }

    public int multi(int i, int j) {
        int result =i*j;
        return result;
    }

    public int div(int i, int j) {
        int result =i/j;
        return result;
    }

}

3.定义代理类

public class CalcLoggingProxy {
 //要代理的对象
  private Calc target;
  public CalcLoggingProxy(Calc target) {
    this.target=target;
    }
  public Calc getLoggingProxy(){
      Calc proxy=null;
      //代理对象由哪一个类加载器加载
      ClassLoader loader=target.getClass().getClassLoader();
      //代理对象的类型,即其中有哪些方法
      Class[] interfaces = new Class[]{Calc.class};
     //当调用代理对象其中的方法试,就执行该方法
    InvocationHandler h=new InvocationHandler() {
        /**
         * proxy:正在返回的代理对象,一般情况下很少使用
         * method:正在调用的方法
         * args:调用方法时,传入的参数
         */
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            
            System.out.println("the method "+method.getName() +" begin with"+ Arrays.asList(args));
            //执行target的方法,即执行代理对象的方法
            Object result=method.invoke(target, args);
            System.out.println("the method "+method.getName() +" end with "+result);
            return result;
        }
    };
        proxy=(Calc) Proxy.newProxyInstance(loader, interfaces, h);
        return proxy;
  }
}

4.写个main方法测试效果

    public static void main(String[] args) {
        Calc target =new CalcImpl();
        Calc proxy =new CalcLoggingProxy(target).getLoggingProxy();
        int result=proxy.add(1, 2);
        System.out.println("--->"+result);
    }

结果如下:

the method add begin with[1, 2]
the method add end with 3
--->3

用动态代理可以解决问题,但是用过spring的同学,肯定非常清楚spring中的AOP能轻松的解决此问题。

原文地址:https://www.cnblogs.com/sunshine2017/p/7353616.html