JDK动态代理和CGLIB动态代理举例

前言

代理模式的实现分为静态代理和动态代理,静态代理比较简单,动态代理分为JDK 动态代理和CGLIB动态代理,本文举一个JDK动态代理的小例子。

接口和接口实现类
  • MyInterface.java
public interface MyInterface {
	void printName(String name);
}
  • MyClass.java
public class MyClass implements MyInterface {
	@Override
	public void printName(String name) {
		System.out.println("Your name is "+name);
	}
}
JDK 动态代理

JDK 的基础类库为我们提供了动态代理的实现方案。
需要四个点,3和4可以写到2中,也可以单独写通过构造方法传递到2中:
1、创建接口和接口实现类
2、实现 java.lang.reflect.InvocationHandler 接口,从写 invoke 方法,invoker 方法内部使用反射机制调用目标对象的方法
3、自定义方法 将目标对象委托给代理对象
4、将目标对象传递给 invoke 方法

实现 InvocationHandler 构建代理对象

构建代理对象的过程可以单独存在,不过那样要将目标对象通过构造方法传递到实现类内部,本文参考了 《深入浅出 Mybatis 技术原理与实战》,写在了实现类内部,综合考虑,这样其实使代码简洁了很多。

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

/**
 * JDK 动态代理
 * @author WuJie
 */
public class MyJDKProxy implements InvocationHandler {

	//真实的服务对象
	private Object target;
	
	/**
	 * 将目标对象委托给代理对象并返回代理对象
	 * @param target
	 * @return
	 */
	public Object bind(Object target){
		this.target=target;
		//取得代理对象
		return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
	}
	
	
	/**
	 * 当通过代理实例化接口并调用接口方法时,将自动调用 invoke 方法,invoke 方法内部通过反射机制调用目标对象的方法
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		System.out.println("自动运行开始");
		//反射机制调用方法
		method.invoke(target,args);
		System.out.println("自动运行结束");
		return null;
	}

}
测试方法
import org.junit.Test;
/**
 * JDK动态代理测试
 * @author WuJieJecket
 *
 */
public class TestMyJDKProxy {
	@Test
	public void testPrintName(){
		MyJDKProxy myProxy=new MyJDKProxy();
		MyInterface myInterface=(MyInterface)myProxy.bind(new MyClass());
		myInterface.printName("Jecket");
	}
}
结果
自动运行开始
Your name is Jecket
自动运行结束
CGLIB 动态代理

和JDK动态代理相比,接口不是必须的,当然也可以有

实现 MethodInterceptor 构建代理对象
import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class MyCglibProxy implements MethodInterceptor {
	private Object target;
	
	/**
	 * 创建代理对象
	 * @param target
	 * @return
	 */
	public Object bind(Object target){
		//传递目标对象
		this.target=target;
		//Enhancer:增强者
		Enhancer enhancer=new Enhancer();
		
		enhancer.setSuperclass(target.getClass());
		
		enhancer.setCallback(this);
		
		//创建代理对象
		return enhancer.create();
	}

	@Override
	public Object intercept(Object arg0, Method arg1, Object[] arg2,
			MethodProxy arg3) throws Throwable {
		System.out.println("自动调用开始");
		//arg1.invoke(target, arg2);
		arg3.invoke(target, arg2);
		System.out.println("自动调用结束");
		return null;
	}
}
测试方法
import org.junit.Test;
/**
 * JDK动态代理测试
 * @author WuJieJecket
 *
 */
public class TestMyCglibProxy {
	//接口模式
	@Test
	public void testPrintName(){
		MyCglibProxy myProxy=new MyCglibProxy();
		MyInterface myInterface=(MyInterface)myProxy.bind(new MyClass());
		myInterface.printName("Jecket");
	}
	
	//非接口模式
	@Test
	public void testPrintName2(){
		MyCglibProxy myProxy=new MyCglibProxy();
		MyClass myClass=(MyClass)myProxy.bind(new MyClass());
		myClass.printName("Jecket");
	}
}
结果
自动调用开始
Your name is Jecket
自动调用结束
自动调用开始
Your name is Jecket
自动调用结束

参考文档

[1]、https://www.cnblogs.com/luoquan/p/5304296.html
[2]、https://www.cnblogs.com/MOBIN/p/5597215.html
[3]、《深入浅出 Mybatis 技术原理与实战》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值