2021-08-21学习日志(代理模式)

代理模式

什么是代理模式:
由于某些原因需要给某对象提供一个代理以控制对该对象的访问,这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。

结构

代理类(Proxy)
目标类(Target)

静态代理

代理类和目标类需要实现同一个接口,在目标类中实现方法的主要逻辑(核心代码)

public class DemoDAOImpl implements IDemoDAO{
	@Override
	public void executeInsert() {
		System.out.println("[数据访问操作]:1.连接数据库");
		System.out.println("[数据访问操作]:2.执行SQL");
		System.out.println("[数据访问操作]:3.处理结果");
	}
}

在代理类中实现增强逻辑(公共代码)在创建目标类对象,调用目标类方法。从而实现不改变核心代码的前提下改变代码的输入内容。

public class DemoDAOpoxy implements IDemoDAO {
	private DemoDAOImpl demoDaoImpl = new DemoDAOImpl();
	@Override
	public void executeInsert() {
		long beginTime = System.currentTimeMillis();
		System.out.println("[增强操作]:executeInsert方法于"+new Date()+"开始执行...");
		demoDaoImpl.executeInsert();
		long endTime = System.currentTimeMillis();
		System.out.println("[增强操作]:executeInsert方法于"+new Date()+"结束执行!!!");
		long time = endTime-beginTime;
		System.out.println("[增强操作]:共耗时:"+time+"毫秒");
	}
}

动态代理

为了应对大规模的代理需求,则需要有一种可针对不同的目标类创建不同的代理对象的代理工厂(利用反射)。动态代理的出现实现了这一需求。
动态代理有两种,一种是基于JDK的动态代理工厂,一种是基于Cglib的动态代理工厂。下面介绍这两种代理工厂的结构。

基于JDK的动态代理工厂

前提:目标类必须实现接口。工厂类则需实现InvocationHandler接口

public class JdkProxyFactory implements InvocationHandler {
	//目标对象
	private Object target;
	
	//构造方法
	//传入目标对象
	public JdkProxyFactory(Object target) {
		this.target = target;
	}
	
	//创建“动态代理对象”
	public Object createProxy() {
		
		//1.获取目标对象的Class对象
		Class targetClass = target.getClass();
		
		//2.通过 java.lang.reflect.Proxy 创建一个新的动态代理实例对象
		// 参数1:目标对象的Class对象的ClassLoader
		// 参数2:目标对象的是实现类接口(数组)
		// 参数3:InvocationHandler接口实现类(当前类)
		Object newProxy = Proxy.newProxyInstance(targetClass.getClassLoader(), targetClass.getInterfaces(), this);
		return newProxy;
	}
	
	/*
	 * 参数1:proxy:当前产生的代理对象
	 * 参数2:method:目标方法
	 * 参数3:args:目标方法的参数
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		long beginTime = System.currentTimeMillis();
		System.out.println("[增强操作]:"+method.getName()+"方法于"+new Date()+"开始执行...");
		System.out.println("目标方法:"+method);
		System.out.println("方法参数:"+Arrays.toString(args));
		
		//完成目标方法的执行(反射)
		//method.invoke(目标对象, 方法参数)
		Object resultVal = method.invoke(target, args);
		
		long endTime = System.currentTimeMillis();
		System.out.println("[增强操作]:"+method.getName()+"方法于"+new Date()+"结束执行!!!");
		System.out.println("[增强操作]:共耗时:"+(endTime-beginTime)+"毫秒");
		
		return resultVal;
	}

}

基于Cglib的动态代理工厂

通过继承实现,实际上就是工厂类成为目标类的父类

public class CglibProxyFactory implements MethodInterceptor{
	//目标对象
	private Object target;
	//构造方法
	public CglibProxyFactory(Object target) {
		this.target = target;
	}
	
	//创建动态代理对象
	public Object createProxy() {
	
		Enhancer enhancer = new Enhancer();
		
		//传入目标对象的Class类型(父类)
		enhancer.setSuperclass(target.getClass());
		
		//设置回调对象:当通过代理对象调用目标方法时,会执行回调对象的intercept()
		enhancer.setCallback(this);
		
		//创建动态代理对象
		Object newProxy = enhancer.create();
		return newProxy;
	}
	
	/*
	 * 参数1:proxy:当前产生的代理对象
	 * 参数2:method:目标方法
	 * 参数3:args:目标方法参数
	 */
	@Override
	public Object intercept(Object proxy, Method method, Object[] args, MethodProxy arg3) throws Throwable {
		System.out.println("********************");
		Object result = method.invoke(target, args);
		System.out.println("$$$$$$$$$$$$$$$$$$$$");
		return result;
	}

}

区别

如果目标类可实现接口,则优先选择JDK的代理工厂,如果目标类因为某些业务不能实现接口,可选择使用Cglib代理工厂。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值