zoukankan      html  css  js  c++  java
  • java动态代理(笔记)

    动态代理比较常见的用处就是:在不修改类的源码的情况下,通过代理的方式为类的方法提供更多的功能。
    java动态代理的实现分为两种:JDK的动态代理与CGILB的动态代理,由于CGILB动态代理是第三方接口实现,大部分实现还是由JDK为主,这里就以JDK做记录
    (这个例子在开发中很常见):开发们实现了业务部分的所有代码,忽然我期望在这些业务代码中多添加日志记录功能的时候,一个一个类去添加代码就会非常麻烦,这个时候我们就能通过动态代理的方式对期待添加日志的类进行代理。

    主要调用接口为InvocationHandler与Proxy
    看一个简单的demo:
    Work接口需要实现work函数

    
    public interface Work {
        public String work();
    }
    
    

    Teacher类实现了Work接口

    
    public class Teacher implements Work{
        @Override
        public String work() {
            System.out.println("my work is teach students");
            return "Teacher";
        }
    }
    
    

    WorkHandler用来处理被代理对象,它必须继承InvocationHandler接口,并实现invoke方法

    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    public class WorkHandler implements InvocationHandler{
        //代理类中的真实对象
        private Object obj;
        //构造函数,给我们的真实对象赋值
        public WorkHandler(Object obj) {
            this.obj = obj;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //在真实的对象执行之前我们可以添加自己的操作
            System.out.println("before invoke。。。");
            //java的反射功能,用来调用obj对象的method方法,传入参数为args
            Object invoke = method.invoke(obj, args);
            //在真实的对象执行之后我们可以添加自己的操作
            System.out.println("after invoke。。。");
            return invoke;
        }
    }
    
    

    在Test类中通过Proxy.newProxyInstance进行动态代理,这样当我们调用代理对象proxy对象的work方法的时候,实际上调用的是WorkHandler的invoke方法。

    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    public class Test {
        public static void main(String[] args) {
            //要代理的真实对象
            Work people = new Teacher();
            //代理对象的调用处理程序,我们将要代理的真实对象传入代理对象的调用处理的构造函数中,最终代理对象的调用处理程序会调用真实对象的方法
            InvocationHandler handler = new WorkHandler(people);
            /**
             * 通过Proxy类的newProxyInstance方法创建代理对象,我们来看下方法中的参数
             * 第一个参数:people.getClass().getClassLoader(),使用handler对象的classloader对象来加载我们的代理对象
             * 第二个参数:people.getClass().getInterfaces(),这里为代理类提供的接口是真实对象实现的接口,这样代理对象就能像真实对象一样调用接口中的所有方法
             * 第三个参数:handler,我们将代理对象关联到上面的InvocationHandler对象上
             */
            Work proxy = (Work)Proxy.newProxyInstance(handler.getClass().getClassLoader(), people.getClass().getInterfaces(), handler);
            System.out.println(proxy.work());
        }
    }
    
    

    看一下输出结果,我们再没有改变Teacher类的前提下通过代理Work接口,实现了work函数调用的重写。

    
    before invoke。。。
    my work is teach students
    after invoke。。。
    Teacher
    
    
  • 相关阅读:
    【校招面试 之 C/C++】第23题 C++ STL(五)之Set
    Cannot create an instance of OLE DB provider “OraOLEDB.Oracle” for linked server "xxxxxxx".
    Redhat Linux安装JDK 1.7
    ORA-10635: Invalid segment or tablespace type
    Symantec Backup Exec 2012 Agent for Linux 卸载
    Symantec Backup Exec 2012 Agent For Linux安装
    You must use the Role Management Tool to install or configure Microsoft .NET Framework 3.5 SP1
    YourSQLDba介绍
    PL/SQL重新编译包无反应
    MS SQL 监控数据/日志文件增长
  • 原文地址:https://www.cnblogs.com/jicklun/p/13993067.html
Copyright © 2011-2022 走看看