zoukankan      html  css  js  c++  java
  • java 动态代理(模式) InvocationHandler(为类中方法执行前或后添加内容)

    动态代理属于Java反射的一种。

    当我们得到一个对象,想动态的为其一些方法每次被调用前后追加一些操作时,我们将会用到java动态代理。

    下边上代码:

    首先定义一个接口:

    package com.liuyx;
    
    public interface Itf {
        public abstract void printMe();
    
        public abstract void printSth(String me);
    }

    接着是它的实现:

    package com.liuyx;
    
    public class Cls implements Itf {
    
        @Override
        public void printMe() {
            System.out.println("I'm Cls!");
        }
    
        @Override
        public void printSth(String str) {
            System.out.println(str);
        }
    
    }

    我们的目的就是通过动态代理技术,在Cls这个类的对象的两个方法执行前后,加上一些打印操作。

    现在我们实现一个InvocationHandler,把我们想要通过代理者被代理者追加的操作都写在invoke方法里面:

    package com.liuyx;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class StandardInvocation implements InvocationHandler {
    
        private Object obj;
        
        StandardInvocation(Object obj){
            this.obj=obj;
        }
        
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("before method excute!");
            Object result = method.invoke(obj, args);
            System.out.println("after method excute!");
            return result;
        }
    
    }

    首先、这里面有一个obj,这个obj是必须的,我们既然要做代理,我们必须知道我们是给谁做代理,这里的obj就是被代理者。

    动态代理说到底也是代理,代理模式里就要求有一个被代理者。

    然后是invoke的三个参数、第一个参数就是代理者,如果你想对代理者做一些操作可以使用这个参数;第二个就是被执行的方法,第三个是执行该方法所需的参数。

    当你执行代理者的某个方法的时候,最后跑的都是invoke方法。

    然后是用法:

        public static void main(String[] args) {
            //创建一个被代理者
            Cls c = new Cls();
            //创建一个InvocationHandler,描述我们希望代理者执行哪些操作
            InvocationHandler i = new StandardInvocation(c);
            //通过刚才创建的InvocationHandler,创建真正的代理者。第一个参数是类加载器,第二个参数是这个代理者实现哪些接口
            Itf pxy = (Itf) Proxy.newProxyInstance(Cls.class.getClassLoader(), new Class[] { Itf.class }, i);
            pxy.printSth("Hi");
        }

    pxy就是c的代理者。

    最后来一个稍微改进的写法:

    package com.liuyx;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class InvocationHandlerTest implements InvocationHandler {
    
        private Object target;
    
        Object bind(Object i) {
            target = i;
            Object warpedItf;
            warpedItf = Proxy.newProxyInstance(target.getClass().getClassLoader(), i.getClass().getInterfaces(), this);
            return warpedItf;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("before method excute!");
            method.invoke(target, args);
            System.out.println("after method excute!");
            return null;
        }
        
        public static void main(String[] args) {
            Cls c = new Cls();
            InvocationHandlerTest pxy = new InvocationHandlerTest();
            Itf itf = (Itf)pxy.bind(c);
            itf.printSth("Hello");
        }
    
    }

    java动态代理有一定局限性,需要定义至少一个接口,使用cglib则不必如此。

  • 相关阅读:
    Git
    系统设计基础
    Java框架之Hibernate(二)
    Java框架之Hibernate(一)
    Java框架之Spring MVC(二)
    Java框架之Spring MVC(一)
    Java框架之Spring(五)
    Java框架之Spring(四)
    Java框架之Spring(三)
    Spring中四种实例化bean的方式
  • 原文地址:https://www.cnblogs.com/flying607/p/3464268.html
Copyright © 2011-2022 走看看