Java代理相关:JDK动态代理、CGLIB动态代理
时间:2022-07-22
本文章向大家介绍Java代理相关:JDK动态代理、CGLIB动态代理,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
代理的三种方式:JDK静态代理、JDK动态代理、CGLIB动态代理
代理(Proxy)是一种设计模式,提供了对目标对象另外的一种访问方式。可以在目标对象实现的基础上,增加额外的功能操作,即扩展目标对象的功能。
其实就类似于Python中的注解。
java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
- 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
- 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
- 如果目标对象没有实现了接口,必须采用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
- [PhalApi实战篇(1)]Redis队列处理异步任务
- 修饰者模式
- PhalApi-RabbitMQ基于PhalApi专业队列拓展
- Python的三个问题
- [喵咪开源软件推荐(4)]Liunx跑分神器-unixbench
- 正则化贪心森林(RGF)的入门简介,含案例研究
- 数据库分库分表中间件 Sharding-JDBC 源码分析 —— SQL 路由(二)之分库分表路由
- [喵咪开源软件推荐(3)]全球IP库-GeoLite2-City
- [喵咪MQ(3)]RabbitMQ集群安装配置
- 动态实现指定图片半透明及鼠标事件
- JVM杂谈之JIT
- 熔断器 Hystrix 源码解析 —— 执行结果缓存
- [喵咪MQ(2)]RabbitMQ单机模式使用
- [喵咪MQ(1)]RabbitMQ简单介绍准备工作
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法