java的3种动态代理 —— jdk、 javassist、cglib动态代理

42 篇文章 2 订阅
29 篇文章 3 订阅


最近想总结一下java的动态代理,动态代理有很多种实现方案,下面介绍三种最常用的动态代理方案:

  1. jdk 动态代理
  2. javassist 动态代理
  3. 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倍

  • 7
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值