zoukankan      html  css  js  c++  java
  • 关于java动态代理的实现

    动态代理主要解决一个问题:面向切面编程aop

    如:日志、探针监控/mybatis的实现原理

    动态代理原理一句话描述:

    首先需要依赖一个interface,然后需要一个增强器hander,然后需要一个proxy根据素材去动态的实现这个接口。

    • interface:是动态代理的对象
    • hander:是怎么样去增强这个代理对象被调用的方法。
    • proxy:是一个调度,告诉JVM在运行期动态用什么素材(interface和hander等)创建实现类的class字节码并加载的过程,以供调用,默认是注入到内存里面,不生成具体的.class文件(可以修改配置参数让其生成)

    直接上demo

    ->接口类

    package com.example.demo.proxy;
    
    public interface Animal {
    
        void eat(String s);
    }

    ->实现类

    package com.example.demo.proxy;
    
    public class Cat implements Animal {
        public void eat(String s) {
            System.out.println("hello world");
        }
    }

    ->增强handler

    package com.example.demo.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class Handler implements InvocationHandler {
        private Animal animal;
    
        public Handler() {
            super();
        }
    
        public Handler(Animal animal) {
            super();
            this.animal = animal;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
            System.out.printf("前置增强
    ");
            System.out.printf(method.getName() + " " + args[0]+"
    ");
            if (this.animal != null) {
                method.invoke(animal, args);
            }
    
            System.out.printf("后置增强
    ==========================
    ");
            return null;
        }
    }

    ->测试

    package com.example.demo.proxy;
    
    import java.lang.reflect.Proxy;
    
    public class Test {
        public static void main(String[] args) throws NoSuchMethodException {
    
            //接口类的动态代理,让接口也可以实例化并调用接口方法并实现方法增强
            InvocationHandler handler1 = new Handler();
    
            Animal proxy1 = (Animal) Proxy.newProxyInstance(
                    Animal.class.getClassLoader(),
                    new Class[] { Animal.class }, 
                    handler1); 
            proxy1.eat("meat");
            
            //实现类的动态代理并实现方法增强
            Animal animal = new Cat();
            InvocationHandler handler2 = new Handler(animal);
    
            Animal proxy2 = (Animal) Proxy.newProxyInstance( 
                    Animal.class.getClassLoader(), // 传入ClassLoader,确定要用哪个加载器来加载.class
                    new Class[] { Animal.class }, // 传入要实现的接口,这里也意味这这种方式,只能支持接口或者实现类的动态代理。
                    handler2); // 传入处理调用方法的InvocationHandler,核心方法,在实例化这个接口的时候,重写类方法,用来增强类方法的逻辑依据。
                    //如果hander里面没有传入接口的实例,则只增强这个空的接口方法。例如mybatis的动态代理,实现dao接口层和mapper.xml的绑定。
                    //如果hander里面有传入接口的实例,则可以在这个增强逻辑里面调用这个实例方法,实现aop注入。
    proxy2.eat("meat"); } }

    ->结果

    暗夜之中,才见繁星;危机之下,暗藏转机;事在人为,为者常成。
  • 相关阅读:
    gcc各个版本下载
    加减法运算解决乘除法
    蚂蚁碰撞的概率
    ns2.34移植leach协议
    ubantu16.04安装ns2.34 错误
    ubantu安全卸载火狐浏览器
    post和get的区别
    docker加速配置阿里云镜像
    重装系统后,会因为本机保存的公匙不对报错
    集合 set
  • 原文地址:https://www.cnblogs.com/zenghansen/p/14707251.html
Copyright © 2011-2022 走看看