Java动态代理

08145526.png

说起动态代理,大家可能都很熟悉,个人自认为动态代理最大的优势就是对原对象无任何侵入的情况下,可以对该对象中的某一方法进行扩展。体现最直接就是Spring中当的Aop了,还有Mybatis中的interface。
动态代理可以分为两种:
1.JDK动态代理,在运行时,jvm动态的生成代理类的class字节码数据,然后从字节码数据中创建代理对象的Class实例,拿到Class实例后通过Java反射生成代理类。这个二进制文件可以是本地,也可以是网络的只要能被java验证通过就可以创建成新的对象。
具体示例如下:
父类接口:

package com.example.demo.proxy.jdk;

public interface Person {

    void doing();
}

子类:

package com.example.demo.proxy.jdk;

public class Kevin implements Person {
    @Override
    public void doing() {
        System.out.println("I like basketball.");
    }
}

代理类:

package com.example.demo.proxy.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class KevinProxy implements InvocationHandler{

    private Object target;
    public KevinProxy(Object target){
        this.target= target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("do before.");
        Object result= method.invoke(target,args);
        System.out.println("do after.");
        return result;
    }
}

测试:

package com.example.demo.proxy.jdk;

import java.lang.reflect.Proxy;


public class Test {

    public static void test(){
        Person person= (Person) Proxy.newProxyInstance(Kevin.class.getClassLoader(),Kevin.class.getInterfaces(),new KevinProxy(new Kevin()));
        person.doing();
        System.out.println(person.getClass().getName());
    }

    public static void main(String[] args) {
        test();
    }
}

2.CGLIB动态代理是基于java开源字节码生成框架ASM,它可以以二进制的形式修改或者生成新的类,在运行时动态生成一个要代理类的子类,因为是子类所以final方法不能被重写。
代码如下:
接口:

package com.example.demo.proxy.cglib;

public class Lisa {
    public void doing(){
        System.out.println("lisa like coffee");
    }
}

代理类:

package com.example.demo.proxy.cglib;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class LisaProxy implements MethodInterceptor {
    private Enhancer enhancer= new Enhancer();

    public Object getProxy(Class clazz){
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("doing before");
        Object result= methodProxy.invokeSuper(o,objects);
        System.out.println("doing end");
        return result;
    }
}

测试:

package com.example.demo.proxy.cglib;

public class Test {

    public static void main(String[] args) {
        Lisa lisa= (Lisa) new LisaProxy().getProxy(Lisa.class);
        lisa.doing();
        System.out.println(lisa.getClass().getName());
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 基础:class文件简介及加载流程 Java编译器编译好Java文件之后,产生.class 文件在磁盘中。这种cl...
    jiangmo阅读 3,297评论 0 1
  • 在工作之余看一些优秀源码的时候发现很多地方使用了动态代理,所以抽了一些时间对java的动态代理深入熟悉一下,这篇文...
    半支铅笔半块橡皮阅读 3,414评论 0 3
  • 唐山这座城市,被一代又一代的人们所熟知,并不是因为它的发达,而是因为四十年前的那场毁灭性的大地震。 三十年过去,当...
    cola的春天阅读 3,332评论 0 7
  • 今天是入职的第一天,正好是建军节,这是一个值得纪念的日子,因为我终于有了自己心仪的工作,虽然工资不高,但希望自己朝...
    汤书姑娘阅读 1,566评论 0 1
  • 一 天已经很黑了,我锁门下楼走出小区,顺着街慢悠悠往...
    燕复生阅读 1,761评论 0 0