关于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("前置增强\n");
        System.out.printf(method.getName() + " " + args[0]+"\n");        if (this.animal != null) {
            method.invoke(animal, args);
        }

        System.out.printf("后置增强\n==========================\n");        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");
    }
}

->结果

关于java动态代理的实现

 

上一篇:c语言中枚举类型


下一篇:牛客历年机试真题--猫狗收容所(队列)