专栏首页若是烟花Java代理相关:JDK动态代理、CGLIB动态代理

Java代理相关:JDK动态代理、CGLIB动态代理

代理的三种方式:JDK静态代理、JDK动态代理、CGLIB动态代理

代理(Proxy)是一种设计模式,提供了对目标对象另外的一种访问方式。可以在目标对象实现的基础上,增加额外的功能操作,即扩展目标对象的功能。

其实就类似于Python中的注解。

java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

  1. 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
  2. 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
  3. 如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

基础类

接口

/**
 * @author lpe234
 * @datetime 2018/7/7 10:44
 */
public interface Person {
    void sayHello();
}

实现类

/**
 * @author lpe234
 * @datetime 2018/7/7 10:45
 */
public class Jim implements Person {

    @Override
    public void sayHello() {
        System.out.println("hello world");
    }
}

JDK静态代理

只能实现对“特定接口的实现类”进行代理。

/**
 * 静态代理
 *
 * @author lpe234
 * @datetime 2018/7/7 10:49
 */
public class Proxy implements Person {

    private Person person;

    public Proxy(Person person) {
        this.person = person;
    }

    @Override
    public void sayHello() {
        System.out.println("invoke before .......");
        person.sayHello();
        System.out.println("invoke after .......");
    }
}

JDK动态代理

可以实现对多种类的代理。

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

/**
 * @author lpe234
 * @datetime 2018/7/7 10:53
 */
public class ProxyJdk implements InvocationHandler {

    private Object object;

    public Object getInstance(Object object) {
        this.object = object;
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
    }

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

CGLIB动态代理

CGLIB(Code Generation Library)是一个开源项目。CGLIB可以在运行时动态生成字节码。 可代理任意一个目标类,但对final类和方法无法代理。

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.7</version>
</dependency>
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * @author lpe234
 * @datetime 2018/7/7 11:01
 */
public class ProxyCglib implements MethodInterceptor {
    private Object object;

    public Object getInstance(Object object) {
        this.object = object;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(object.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("invoke before .......");
        method.invoke(this.object, objects);
        System.out.println("invoke after .......");
        return null;
    }
}

运行

/**
 * @author lpe234
 * @datetime 2018/7/7 10:44
 */
public class Main {

    public static void main(String[] args) {

        System.out.println("静态代理");
        Proxy proxy = new Proxy(new Jim());
        proxy.sayHello();

        System.out.println("\n");
        System.out.println("JDK动态代理");
        Person person = (Person) new ProxyJdk().getInstance(new Jim());
        person.sayHello();

        System.out.println("\n");
        System.out.println("Cglib动态代理");
        Person person1 = (Person) new ProxyCglib().getInstance(new Jim());
        person1.sayHello();
    }
}

运行结果:

静态代理
invoke before .......
hello world
invoke after .......


JDK动态代理
invoke before .......
hello world
invoke after .......


Cglib动态代理
invoke before .......
hello world
invoke after .......

Process finished with exit code 0

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Dizzy Blog

    lpe234
  • python提高--running-python-code-contained-in-a-strin

    http://stackoverflow.com/questions/701802/how-do-i-execute-a-string-containing-p...

    lpe234
  • 七日Python之路--第十二天(Django Web 开发指南)

    《Django Web 开发指南》。貌似使用Django1.0版本,基本内容差不多,细读无妨。地址:http://www.jb51.net/books/7607...

    lpe234
  • Dataset - Visual Genome 数据集格式

    [... { "image_id": 2412112, "url"...

    AIHGF
  • MYSQL hash join 终于等到她

    MYSQL 的多表联合查询中,只有nest loop 的查询方式,让MYSQL 一致是被“嘲笑”的地方。MYSQL 8.018 后mysql 将拥有HASH J...

    AustinDatabases
  • SpringBoot集成Swagger2

    首先说一下这个东西的作用:它可以很轻松整合到Spring Boot中,并与Spring MVC程序配合组织出强大RESTful API文档。简单说就是Swagg...

    乐心湖
  • Spring、Spring Boot和TestNG测试指南 - @ActiveProfiles

    @ActiveProfiles可以用来在测试的时候启用某些Profile的Bean。本章节的测试代码使用了下面的这个配置:

    颇忒脱
  • 那些年我们用Java写过的小游戏 --- 快速击键系统

    训练技能点 面向对象设计的思想 使用类图理解类的关系 类的封装 构造方法的使用 this、static关键字的使用 需求概述 根据输入速率和正确率将玩家分为不同...

    房上的猫
  • 第三阶段-Java常见对象:【第八章 System类】

    System.gc() 可用于垃圾回收.当使用System.gc() 回收某个对象所占用的内存之前,通过要求程序调用适当的方法来清理资源,在没有明确指定资源清理...

    BWH_Steven
  • WPF创建仿迅雷下载地址下拉选择框—ComboBox

    升级了迅雷7,感觉视觉上的确给人了耳目一新的感觉。我照葫芦画瓢吧仿造了一个迅雷选择下载的下拉框

    yoyofx

扫码关注云+社区

领取腾讯云代金券