动态代理模式

这也是ssm框架和redis实现的重点内容之一
知道AOP的这里肯定好懂,但看完这个可以更好的去学习AOP
什么是代理模式
顾客去小餐馆吃饭,本质上是找厨师,事实上我们一般见不到厨师。很多情况下找前台服务员。
在吃饭之前,通过服务员了解厨师可以做出什么菜,以及价格等等,不满意,就不吃了,满意的话,才去吃厨师做的菜。
吃完之后,我们可以去前台服务员那反映情况,买单,对厨师做出评价,以及一些后续的事
显然,顾客是通过前台服务员访问这个厨师,你想吃什么,显然不会和厨师说,而是和服务员谈,那么这个服务员(代理对象)起到什么作用呢?
在吃饭之前,交代菜品、价格、上菜的时间。。。也有可能顾客了解完后不符合自己的口味不吃了,吃完饭可以收费,听取顾客的反映,这些都不需要厨师来处理
代理的作用就是:在真实对象访问之前或者之后加入一些逻辑(目的之外的琐事处理),根据一些规则控制是否访问真正的对象
此时,客户是经过服务员访问厨师的,客户就是程序的调用者,服务员就是代理对象,厨师就是被代理对象,代理对象需要和真实对象建立代理关系
所以代理分为两个步骤:
1、代理对象和真实对象建立代理关系(服务员说:厨师就去做饭,我知道你做的所有菜品,顾客来了我代表你)
2、实现代理对象的代理逻辑方法(顾客来吃饭,我来处理从顾客进门询问到吃你做的菜以及买单等等后续的事)
Java中有很多动态代理技术,比如JDK、cglib、Javassist、ASM,最常用的就是JDK和cglib,无论哪种,代理技术的理念都是一样的

JDK动态代理

JDK自带的功能,是java.lang.reflect.*包提供的方式
被代理对象所属的类必须实现接口
先写一个接口,一个实现接口的类

public interface cook
{
public void fan();
}
public class cookImpl implements cook
{
public void fan()
{
System.out.println("厨师做饭给顾客吃");
}
}

代理类要实现java.lang.reflect.InvocationHandler,里面有一个invoke方法,可以实现代理逻辑方法,还有一个接口数组用于挂着代理对象,声明代理对象时,可以向上转型为接口类型

public class JDKproxy implements InvocationHandler
{
private Object cookOne=null;  //真实对象 厨师1
//建立代理对象和真实对象的关系,生成代理对象
public  Object bind (Object cookOne)
{
this.cookOne=cookOne;
//newProxyInstance三个参数
//第一个是对象cookOne所在类的类加载器
//第二个是把生成的代理对象挂在哪些接口下
//this指的当前对象,意思是某一个对象调用了本类中的方法,那么这个this就表示这个对象。这个对象必须实现invoke方法
return Proxy.newProxyInstance(cookOne.getClass().getClassLoader(),cookOne.getClass().getInterface(),this)
}
//实现代理逻辑方法
//proxy就是bind方法生成的代理对象
//method代表当前要调度的方法 fan()
//args  调度方法的参数
public Object invoke(Object proxy,Methos method,Object[] args)throws Throwable
{
System.out.println("给顾客介绍厨师做的菜,价格,提供服务");
Object obj=method.invoke(cookOne,args);//相当于真实对象厨师要做的事
System.out.println("吃饭会顾客结账,提供后续服务,欢迎下次光临");
}
}

当使用代理对象调度方法时,就会按invoke方法执行
proxy.fan();
测试一下

public static void main(String args[])
{
JDKproxy jdkproxy=new JDKproxy();
//第一步,绑定关系  挂在接口下就可以这样申明代理对象
cook waitorproxy=(cook)jdkproxy.bind(new cookImpl());
//第二步,实现逻辑代理方法
waitorproxy.fan();
}


给顾客介绍厨师做的菜,价格,提供服务
厨师做饭给顾客吃
吃饭会顾客结账,提供后续服务,欢迎下次光临

cglib动态代理

JDK动态代理只能代理实现接口的对象,但有些不能提供接口的环境中,只能采用其他第三方技术,第三方库,比如cglib动态代理
还拿厨师为例,不实现接口

public class cook
{
public void fan()
{
System.out.println("厨师做饭给顾客吃");
}
}
public class cglibproxy implements MethodInterceptor
{
//建立代理对象和真实对象的关系,生成代理对象
//原理就是用Enhancer生成一个原有类的子类,并且设置好callback到proxy, 则原有类的每个方法调用都会转为调用实现了MethodInterceptor接口的proxy的intercept() 函数
//在网上搜了好些资料,也没有几个去说enhancer背后的故事,有机会去看源码,记住步骤吧
public Object getProxy(Class cls)
{
//记住步骤,就是背公式
//增强类对象
Enhancer enhancer=new Enhancer();
//将传入的类设为父类
enhancer.setSuperclass(cls);
//设置哪个类为代理类
enhancer.setCallback(this); //设置当前类
//返回代理对象
return enhancer.create();
}
//代理逻辑方法
public Object intercept(Object proxy,Method method,Object[] args,MethodProxy methodProxy)throws Throwable
{
System.out.println("给顾客介绍厨师做的菜,价格,提供服务");
Object result=methodProxy.invokeSuper(proxy,args);//相当于真实对象厨师要做的事
System.out.println("吃饭会顾客结账,提供后续服务,欢迎下次光临");
return result;
}
}
}
public static void main(String args[])
{
cglibproxy cgproxy=new cglibproxy();
cook obj=(cook)cgproxy.getProxy(cook.class);
obj.fan();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值