java基础知识-动态代理

最近几天工作上的事情比较多,没有来得及看写知识总结,还有一个原因是近日心情比较浮躁,没有认真的学习,这两天看了看《架构探险 从零开始写javaweb框架》这本书,挺有意思,让我也弥补了一下java的基础知识,今天就说说动态代理吧。
举个生活中的例子,微商可以看作是代理人,负责为厂家卖东西,当然厂家也有直营店自己也卖。为什么有直营店还要微商呢,其实就是扩充销售渠道,比如茅台酒厂,它自己卖飞天和五星系列,但是由于它在四川,加之早起宣传渠道闭塞,远在其他省份的人根本不知道它的名气,这个时候微商的优势就出来了,比如张三是个微商,代理茅台酒,他可以小范围的售卖,加之自己的人缘好,可能亲戚朋友都会买他的,而张三是个讲究人,未成年人、女孩子他不卖。
以上这个场景如果用代码来实现,如下:

一、静态代理

微商和厂家肯定都做同一件或者几件事,我们可以把这些事提取成接口,当然也可以不提取,直接查看厂家都干哪些事,自己一件一件实现

interface Sale{
void saleWuXing();
void saleFeiTian();
}

class Moutai implement Sale{
	@Override
	public void saleWuXing(){
	System.out.println("Moutai sale WuXing");
	}
	
	@Override
	public void saleFeiTian(){
	System.out.println("Moutai sale FeiTian");
	}

}

class ZhangSan implement Sale{
Sale s = new Moutai();

	@Override
	public void saleWuXing(){
	if("购买人的年龄大于18岁,且是男性”){
	    	s.saleWuXing();
	    }
	}
	
	@Override
	public void saleFeiTian(){
		if("购买人的年龄大于18岁,且是男性,且非常有钱”){
	    	s.saleFeiTian();
	    }
	}

}

可以看到,我们把代码全部写完了,这种在编译时就确定好对象的行为就是静态代理。

二、动态代理

1、通过jdk实现

观察上面的例子,可以确认两点:
1、必须已知并且全部实现被代理对象的方法
2、调用代理的前后可以在某些方法中添加自己的一些逻辑,这也是必须的,否则就没必要代理了

有没有办法可以做到 不用实现每个代理方法就仍可以添加自己的处理逻辑呢?
*(代理类必须完全实现被代理类的方法,如果不需要进行额外处理,那么也需要一个方法一个方法的实现被代理类的方法,在方法里直接调用,例如:
还有一个saleXXX方法,在zhangsan里无需处理,它也要
public void saleXXX(){
s.saleXXX();
}

如果sale接口有1000多个方法,那么需要一个一个去写,而通过动态代理,在invoke()里实现一句即可,method.invoke() )*

在java里用到的就是反射

public class DynamicProxy implements InvocationHandler { 
  
private Object obj; //obj为委托类对象; 
public DynamicProxy(Object obj) { 
  
this.obj = obj; 
  
} 
  
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
Object result = null;
if(method.getName() == "saleWuxing"){
		if("购买人的年龄大于18岁,且是男性”){
	    	result = method.invoke(obj, args); 
	    }else{
	       "您没有购买资格
	    }
}else if(method.getName() == "saleFeiTian"){
		if("购买人的年龄大于18岁,且是男性,且非常有钱”){
	    	esult = method.invoke(obj, args); 
	    }else{
	       "您没有购买资格
	    }
}
return result; 
  
} 
  
} 

// 具体使用过程
public class Main { 
public static void main(String[] args) { 
//创建中介类实例 
  
DynamicProxy zhangsan = new DynamicProxy(new Moutai()); 
Sale sale = (Sale)(Proxy.newProxyInstance(Sale.class.getClassLoader(), new Class[] {Sale.class}, zhangsan)); 
//通过代理类对象调用代理类方法,实际上会转到invoke方法调用 
sale.buyWuxing(); 
sale.buyFeiTian(); 
  
} 
  
} 

InvocationHandler 实现这个接口可以理解为就是创建代理类,只不过不用每个方法都去实现,只需传入被代理的类(这个在静态代理类也有,必须的,要不怎么叫“代理”呢),在invoke里把代理类的方法统一实现即可。

调用时,我们总不能直接调用zhangsan.buyWuxing();因为就没有这个方法,只能通过newProxyInstance动态创建对象,“动态”就体现在这,然后通过返回的接口去调用具体方法。

动态代理的实现步骤
1、定义一个接口
2、创建被代理类实现这个接口
3、创建代理类,通过实现InvocationHandler接口的invoke实现增强,要把被代理类传入
使用时
1、将被代理类传入代理类
2、通过Proxy.newProxyInstance()绑定代理类,并返回接口
newProxyInstance(被代理类的类加载器,被代理类的接口,代理类)
3、通过接口调用代理类,实现增强

总之,就是必须有一个接口,jdk通过接口实现调用

2、通过cglib实现

通过上面jdk实现的逻辑不难发现,给我一个类,我就想对它进行增强,可这个类必须得是实现某一接口的,这个限制太不爽了,有没有办法打破呢,cglib就可以做到。

我们拿上面jdk的步骤进行比对来看
实现步骤
1、定义一个接口
2、创建被代理类实现这个接口 仅是创建一个普通的类
3、创建代理类,通过实现InvocationHandler接口的invoke实现增强,,要把被代理类传入,通过实现MethodInterceptor接口实现增强,不用传入被代理类
使用时
1、通过enhancer实例,将被代理类传入代理类
2、通过setCallback绑定代理类
3、通过creat(),创建被代理类,调用被代理类时已经被默默的增强了。

三、总结

jdk动态代理实际上是通过接口实现的,cglib是通过字节码技术从被代理类入手实现的,两种方法都有自己的妙处,也有不同的用处,没有绝对的好坏之分。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值