zoukankan      html  css  js  c++  java
  • 使用动态代理解决方法调用前后添加日志信息

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

    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能轻松的解决此问题。

  • 相关阅读:
    理解java容器:iterator与collection,容器的起源
    【软件构造】-<笔记>-浅谈java中类的初始化过程
    CSAPP HITICS 大作业 hello's P2P by zsz
    2年经验,java后端必备技术点总结(脑图)
    手把手教,手写AVL树
    Redis源码分析-底层数据结构盘点
    验证mysql事务隔离级别机制加锁情况与MVCC机制
    Layui镜像站
    elasticsearch技术实战——第一篇(使用篇)
    【基础1】JniHelper静态函数和非静态函数的调用
  • 原文地址:https://www.cnblogs.com/sunshine2017/p/7353616.html
Copyright © 2011-2022 走看看