详解JAVA设计模式之代理模式
什么是设计模式(DesignPattern)?
设计模式是一套被反复使用,多数人知晓的,经过分类编目的,代码设计经验的总结。
代理模式的定义?
代理模式就是为其他对象提供一种代理,以控制对这个对象的访问。
代理对象起到中介作用,可去掉功能服务或增加额外的服务。
代理对象和目标对象的关系?
代理对象:增强后的对象
目标对象:被增强的对象
他们不是绝对的,会根据情况发生变化。
代理模式的两种实现方式?
1.静态代理:代理和被代理对象在代理之前是确定的,它们都实现相同的接口或者继承相同的抽象类。
2.动态代理:JDK通过接口反射得到字节码,然后把字节码转换成class(通过native方法)
静态代理实现的两种方式?
使用继承方式实现和使用聚合方式实现。
继承:代理对象继承目标对象,重写需要增强的方法。缺点:代理类过多,产生类爆炸。
聚合:目标对象和代理对象实现同一个接口,代理对象当中要包含目标对象。
动态代理的实现方式?
Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:
1.InterfaceInvocationHandler:该接口中仅定义了一个方法,publicObjectinvoke(Objectobj,Methodmethod,Object[]args),在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,args是该方法的参数数组,这个抽象方法在代理类中动态实现。
2.Proxy该类即为动态代理类,staticObjectnewProxyInstance(ClassLoaderloader,Class[]interfaces,InvocationHandlerh):返回代理类的一个实例,返回后的代理类可以当做被代理类使用(可使用被代理类在接口中声明过的方法)
所谓的动态代理是这样一种class:它是在运行时生成的class,该class需要实现一组interface,使用动态代理类时,必须实现InvocationHandler接口。
JDK动态代理和CGLIB动态代理的区别?
1.JDK动态代理只能代理实现了接口的类,没有实现接口的类不能实现JDK的动态代理。
2.CGLIB动态代理针对类来实现代理的,对指定目标类产生一个子类,通过方法拦截技术拦截所有的父类方法的调用。
动态代理实现的思路:
1.声明一段源码(动态产生代理)
2.编译源码(JDKCompilerAPI),产生新的类(代理类)
3.将这个类load到内存中,产生一个新的对象(代理对象)
4.return代理对象。
使用静态代理的例子:
1.首先创建业务逻辑接口
/** *接口 *@authorAdministrator * */ publicinterfaceMoveable{ /** * *接口中的方法 *@Description:TODO *@returnType:void */ voidmove(); }
2.创建实现类,实现接口中的方法
/** *实现类 *@authorAdministrator * */ publicclassCarimplementsMoveable{ @Override publicvoidmove(){ //实现开车 try{ Thread.sleep(newRandom().nextInt(1000)); System.out.println("汽车行驶中..."); }catch(InterruptedExceptione){ e.printStackTrace(); } } }
3.使用继承方式实现对实现类的代理
/** *使用继承方式实现代理 *@authorAdministrator * */ publicclassCar2extendsCar{ /*(non-Javadoc) *@seecom.wk.design.proxy.Car#move() *直接调用父类的move方法,这样就形成了一个Car2对Car的代理 */ @Override publicvoidmove(){ longstartTime=System.currentTimeMillis(); System.out.println("汽车开始行驶..."); //使用继承的方式调用父类的move()方法 super.move(); longendTime=System.currentTimeMillis(); System.out.println("汽车行驶结束...汽车行驶时间:"+(endTime-startTime)+"毫秒。"); } }
4.创建测试类
/** *测试类 *@authorAdministrator * */ publicclassTest{ publicstaticvoidmain(String[]args){ //Carcar=newCar(); //car.move(); //使用继承方式实现代理 Moveablecar2=newCar2(); car2.move(); //使用聚合方式实现代理 //Carcar=newCar(); //Moveablecar3=newCar3(car); //car3.move(); } }
5.使用聚合方式实现对实现类的代理
日志代理类
/** * *日志代理类 *@authorAdministrator * */ publicclassCarLogProxyimplementsMoveable{ /** *使用接口声明代理类 */ privateMoveablem; /** *通过构造方法的参数传入代理类 *@paramm */ publicCarLogProxy(Moveablem){ super(); this.m=m; } @Override publicvoidmove(){ System.out.println("日志开始"); //调用代理类的方法 m.move(); System.out.println("日志结束"); } }
时间代理类
/** *时间代理类 *@authorAdministrator * */ publicclassCarTimeProxyimplementsMoveable{ /** *使用接口声明代理类 */ privateMoveablem; /** *通过构造方法的参数传入代理类 *@paramm */ publicCarTimeProxy(Moveablem){ super(); this.m=m; } @Override publicvoidmove(){ longstartTime=System.currentTimeMillis(); System.out.println("汽车开始行驶..."); //调用代理类的方法 m.move(); longendTime=System.currentTimeMillis(); System.out.println("汽车行驶结束...汽车行驶时间:"+(endTime-startTime)+"毫秒。"); } }
6.创建聚合方式测试类
/** *聚合代理测试类 *@authorAdministrator * */ publicclassTestJuHeProxy{ publicstaticvoidmain(String[]args){ Carcar=newCar(); //先记录日志,再记录时间 //CarTimeProxyctp=newCarTimeProxy(car); //CarLogProxyclp=newCarLogProxy(ctp); //clp.move(); //先记录时间,再记录日志 CarLogProxyclp=newCarLogProxy(car); CarTimeProxyctp=newCarTimeProxy(clp); ctp.move(); } }
使用JDK动态代理实现的例子:
1.创建一个实现接口InvocationHandler的类,它必须实现invoke()方法。
2.创建被代理类及接口
3.调用Proxy的静态方法,创建一个代理类
4.通过代理调用方法
/** *使用jdk的动态代理 *@authorAdministrator * */ publicclassTimeHandlerimplementsInvocationHandler{ /** *被代理对象 */ privateObjecttarget; publicTimeHandler(Objecttarget){ super(); this.target=target; } /** *参数: *proxy:被代理对象 *method:被代理对象的方法 *args:方法的参数 *返回值: *Object方法的返回值 */ @Override publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{ //在执行被代理对象的方法之前执行自己的逻辑 longstartTime=System.currentTimeMillis(); System.out.println("汽车开始行驶..."); //执行被代理对象的方法 method.invoke(target); //在执行被代理对象的方法之后执行自己的逻辑 longendTime=System.currentTimeMillis(); System.out.println("汽车行驶结束...汽车行驶时间:"+(endTime-startTime)+"毫秒。"); returnnull; } }
/** *JDK动态代理测试类 *@authorAdministrator * */ publicclassJdkProxyTest{ publicstaticvoidmain(String[]args){ Carcar=newCar(); InvocationHandlerh=newTimeHandler(car); Class>cls=car.getClass(); /** *参数: *loader:类加载器 *interfaces:实现接口 *hInvocationHandler */ Moveablem=(Moveable)Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),h); //执行被代理类的方法 m.move(); } }
使用CGLIB动态代理实现的例子:
1.创建代理类,实现MethodInterceptor接口
2.使用Enhancer类创建代理方法
3.创建被代理类,并编写代理方法
4.通过代理调用方法
/** *使用cglib动态代理 *@authorAdministrator * */ publicclassTrain{ publicvoidmove(){ System.out.println("火车行驶中。。。"); } }
publicclassCglibProxyimplementsMethodInterceptor{ privateEnhancerenhancer=newEnhancer(); //创建代理类方法 publicObjectgetProxy(Classclazz){ //设置创建子类的类 enhancer.setSuperclass(clazz); //回调函数 enhancer.setCallback(this); //创建并返回子类的实例 returnenhancer.create(); } /** *作用:拦截所有目标类方法的调用 *obj:目标类的实例 *m:目标方法的反射对象 *args:方法的参数 *proxy:代理类的实例 */ @Override publicObjectintercept(Objectobj,Methodm,Object[]args,MethodProxyproxy)throwsThrowable{ //在调用方法时实现自己的业务逻辑 System.out.println("日志开始..."); //代理类调用父类的方法 proxy.invokeSuper(obj,args); //调用方法之后实现自己的业务逻辑 System.out.println("日志结束..."); returnnull; } }
/** *使用cglib动态代理的测试类 *@authorAdministrator * */ publicclassCglibProxyTest{ publicstaticvoidmain(String[]args){ CglibProxyproxy=newCglibProxy(); //传入要代理的类 Traint=(Train)proxy.getProxy(Train.class); //执行方法 t.move(); } }
以上就是详解JAVA设计模式之代理模式的详细内容,更多关于JAVA代理模式的资料请关注毛票票其它相关文章!