文章目录
- 一、jdk 动态代理
- 1.1、接口:ITeacherDao
- 1.2、目标类:TeacherDao
- 1.3、代理工厂:ProxyFactory
- 1.4、测试类:
- 二、javassist 动态代理
- 2.1、依赖
- 2.2、接口:ITeacherDao
- 2.3、实现类:TeacherDao
- 2.4、代理工厂:MyProxyFactory
- 2.5、测试类
- 三、cglib 动态代理
- 3.1、依赖
- 3.2、目标类: TeacherDao
- 3.3、代理工厂: ProxyFactory
- 3.4、测试类:
最近想总结一下java的动态代理,动态代理有很多种实现方案,下面介绍三种最常用的动态代理方案:
- jdk 动态代理
- javassist 动态代理
- cglib 动态代理
一、jdk 动态代理
1.1、接口:ITeacherDao
package com.aop8.jdk;
//接口
public interface ITeacherDao {
void teach(); // 授课方法
void sayHello(String name);
}
1.2、目标类:TeacherDao
package com.aop8.jdk;
public class TeacherDao implements ITeacherDao {
@Override
public void teach() {
System.out.println(" 老师授课中.... ");
}
@Override
public void sayHello(String name) {
System.out.println("hello " + name);
}
}
1.3、代理工厂:ProxyFactory
核心类:
- Proxy.newProxyInstance() 类
- InvocationHandler 接口
package com.aop8.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactory {
//维护一个目标对象 , Object
private Object target;
//构造器 , 对target 进行初始化
public ProxyFactory(Object target) {
this.target = target;
}
//给目标对象 生成一个代理对象
public Object getProxyInstance() {
/**
* public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
// 参数1. ClassLoader loader : 指定当前目标对象使用的类加载器, 获取加载器的方法固定
// 参数2. Class<?>[] interfaces: 目标对象实现的接口类型,使用泛型方法确认类型
// 参数3. InvocationHandler h : 事情处理,执行目标对象的方法时,会触发事情处理器方法,
// 会把当前执行的目标对象方法作为参数传入
*/
return Proxy.newProxyInstance(target.getClass().getClassLoader(), //参数1,loader
target.getClass().getInterfaces(), //参数2,interfaces
new InvocationHandler() { //参数3,invocationHandler
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDK代理开始~~");
//反射机制调用目标对象的方法
Object returnVal = method.invoke(target, args);
System.out.println("JDK代理提交");
return returnVal;
}
});
}
}
1.4、测试类:
package com.aop8.jdk;
public class Main {
public static void main(String[] args) {
// 创建目标对象
ITeacherDao target = new TeacherDao();
// 给目标对象,创建代理对象, 可以转成 ITeacherDao
ITeacherDao proxyInstance = (ITeacherDao) new ProxyFactory(target).getProxyInstance();
// proxyInstance=class com.sun.proxy.$Proxy0 内存中动态生成了代理对象
System.out.println("proxyInstance=" + proxyInstance.getClass());
// 通过代理对象,调用目标对象的方法
// proxyInstance.teach();
proxyInstance.sayHello("tom");
}
}
运行结果:
proxyInstance=class com.sun.proxy.$Proxy0
JDK代理开始~~
hello tom
JDK代理提交
二、javassist 动态代理
2.1、依赖
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.22.0-GA</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
2.2、接口:ITeacherDao
package com.aop8.javassist;
//接口
public interface ITeacherDao {
String teach();
String sayHello(String name);
}
2.3、实现类:TeacherDao
package com.aop8.javassist;
public class TeacherDao implements ITeacherDao {
@Override
public String teach() {
System.out.println("老师授课中.... ");
return "teach";
}
@Override
public String sayHello(String name) {
System.out.println("hello " + name);
return "teach";
}
}
2.4、代理工厂:MyProxyFactory
核心类:
- MethodHandler 接口
- ProxyFactory 类
- ProxyObject 类
package com.aop8.javassist;
import java.lang.reflect.Method;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory;
import javassist.util.proxy.ProxyObject;
public class MyProxyFactory implements MethodHandler {
// 维护一个目标对象 , Object
private Object target;
private MyProxyFactory() {
}
// 构造器 , 对target 进行初始化
public MyProxyFactory(Object target) {
this.target = target;
}
// 给目标对象 生成一个代理对象
public Object getProxyInstance() {
// 用javassist反射生成代理类
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setInterfaces(target.getClass().getInterfaces());
Class<?> proxyClass = proxyFactory.createClass();
Object objectProxy= null;
try {
personProxy = proxyClass.newInstance();
((ProxyObject) objectProxy).setHandler(this);
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return objectProxy;
}
@Override
public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
System.out.println("javassist ~~ 开始");
Object returnVal = thisMethod.invoke(target, args);
System.out.println("javassist ~~ 完成!!");
return returnVal;
}
}
2.5、测试类
package com.aop8.javassist;
public class Main {
public static void main(String[] args) {
// 创建目标对象
ITeacherDao target = new TeacherDao();
ITeacherDao proxyInstance = (ITeacherDao) new MyProxyFactory(target).getProxyInstance();
String ret = proxyInstance.sayHello("张三");
System.out.println("ret=" + ret);
}
}
运行结果:
javassist ~~ 开始
hello 张三
javassist ~~ 完成!!
ret=teach
三、cglib 动态代理
3.1、依赖
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.5</version>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>3.3.1</version>
</dependency>
3.2、目标类: TeacherDao
package com.aop8.cglib2;
public class TeacherDao {
public String teach() {
System.out.println("老师授课中 , 我是cglib代理,不需要实现接口 ");
return "hello";
}
}
3.3、代理工厂: ProxyFactory
核心类:
- MethodInterceptor 接口
- Enhancer 类
package com.aop8.cglib2;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class ProxyFactory implements MethodInterceptor {
// 维护一个目标对象
private Object target;
// 构造器,传入一个被代理的对象
public ProxyFactory(Object target) {
this.target = target;
}
// 返回一个代理对象: 是 target 对象的代理对象
public Object getProxyInstance() {
// 1. 创建一个工具类
Enhancer enhancer = new Enhancer();
// 2. 设置父类
enhancer.setSuperclass(target.getClass());
// 3. 设置回调函数
enhancer.setCallback(this);
// 4. 创建子类对象,即代理对象
return enhancer.create();
}
// 重写 intercept 方法,会调用目标对象的方法
@Override
public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable {
System.out.println("Cglib代理模式 ~~ 开始");
Object returnVal = method.invoke(target, args);
System.out.println("Cglib代理模式 ~~ 提交");
return returnVal;
}
}
3.4、测试类:
package com.aop8.cglib2;
public class Main{
public static void main(String[] args) {
// 创建目标对象
TeacherDao target = new TeacherDao();
// 获取到代理对象,并且将目标对象传递给代理对象
TeacherDao proxyInstance = (TeacherDao) new ProxyFactory(target).getProxyInstance();
// 执行代理对象的方法,触发intecept 方法,从而实现 对目标对象的调用
String res = proxyInstance.teach();
System.out.println("res=" + res);
}
}
运行结果:
Cglib代理模式 ~~ 开始
老师授课中 , 我是cglib代理,不需要实现接口
Cglib代理模式 ~~ 提交
res=hello
我还做了实验,但从创建来看jdk是最快的cglib最慢,但创建好后调用,javassist最快,jdk次之,不过是同一个数量级的,cglib最慢比其他2种慢5倍