黑马程序员 学习日记(十)
来源:互联网 发布:清朝人口知乎 编辑:程序博客网 时间:2024/06/04 19:18
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------
ShopImpl.java
ShopProxy.java
ShopTest.java
简单的一个静态代理就实现了。重点在于他们都实现了同一个接口,这样才有相同方法,才能在委托类把对象交给代理类的对象的时候确保执行相同方法,实现代理。但在这之余代理可以更自由的去做其他的事情,这就是代理的好处。你随时可以加一个打折促销的广告,夏季冬季随便换也不影响原出售环节。
动态代理
代理是一种设计模式,与现实生活中的代理意思接近。一个类的运行由另一个类去代理运行,这样就可以在目标类的方法运行前后都加入额外的内容去执行,也可以对目标方法的参数进行过滤,委托类与代理类通常存在一个关联。代理设计模式非常有利于程序的管理维护和测试。
1.静态代理
shop.java
package com.itheima.proxy;/** * 定义一个商店接口 * 无论是原商场还是代理商都要实现这个接口 * @author cloud * */public interface Shop {public void sale() ; //卖东西public void stoke() ; //进货}
ShopImpl.java
package com.itheima.proxy;/** * 原商店 * 有出售和进货能力 * @author cloud * */public class ShopImpl implements Shop {@Overridepublic void sale() {System.out.println("卖出一件货物。");}@Overridepublic void stoke() {System.out.println("采购一批货物");}}
ShopProxy.java
package com.itheima.proxy;/** * 代理类 * 代理出售和进货 * @author cloud * */public class ShopProxy implements Shop {private ShopImpl shopImpl ;public ShopProxy(ShopImpl shopImpl){this.shopImpl = shopImpl ;}@Overridepublic void sale() {System.out.println("出售货物之前");shopImpl.sale();System.out.println("出售货物之后");}@Overridepublic void stoke() {System.out.println("进货之前");shopImpl.stoke();System.out.println("进货之后");}}
ShopTest.java
package com.itheima.proxy;/** * 测试 * @author cloud * */public class ShopTest {public static void main(String[] args){ShopImpl shopImpl = new ShopImpl() ;ShopProxy shopProxy = new ShopProxy(shopImpl) ; //把对象交给代理对象shopProxy.sale(); //代理对象在卖东西shopProxy.stoke(); //代理对象 在进货}}
简单的一个静态代理就实现了。重点在于他们都实现了同一个接口,这样才有相同方法,才能在委托类把对象交给代理类的对象的时候确保执行相同方法,实现代理。但在这之余代理可以更自由的去做其他的事情,这就是代理的好处。你随时可以加一个打折促销的广告,夏季冬季随便换也不影响原出售环节。
2.动态代理
但在实际开发中,如果只使用程序员预订编辑好的代理类,每一个接口每一个委托类都要去设计一个代理类,这样做徒然增加工作量,维护起来也很费时费力。最好就是一个代理类能接受所有委托。利用Java的反射机制设计一个代理类使其接受任意代理。
要做这样一个代理,那我们就要仔细思考。首先肯定还是要接收一个对象参数,然后要实现此对象的哪个方法,执行方法可能需要参数。这样就一共需要这三个参数。JDK正好为我们提供了一个接口,
InvocationHandler接口:
public interface InvocationHandler {
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
}
参数说明:
Object proxy:指被代理的对象。
Method method:要调用的方法
Object[] args:方法调用时所需要的参数
public interface InvocationHandler {
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
}
参数说明:
Object proxy:指被代理的对象。
Method method:要调用的方法
Object[] args:方法调用时所需要的参数
接口解决了,那么最关键的类呢?关键就在于这个类必须是动态的,如果写死它最终还是一个静态代理。所以这个类必须要在运行时动态创建。实现动态创建类要使用Proxy类。
把上面的代理类稍微改动一下,接口和委托类不用动。
package com.itheima.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/** * 代理类 * 代理出售和进货 * @author cloud * */public class ShopProxy implements InvocationHandler {private Object target ;public Object bind(ShopImpl target){this.target = target ;return Proxy.newProxyInstance(target.getClass().getClassLoader(), //通过反射创建一个类target.getClass().getInterfaces(), this) ;} //代理对象执行任意方法都会自动来执行一次这个方法。@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {Object result = null ;System.out.println("start");result = method.invoke(target, args) ; //执行委托方法System.out.println("end");return result;}}main方法中也稍微改改,使用方式有所变化
package com.itheima.proxy;/** * 测试 * @author cloud * */public class ShopTest {public static void main(String[] args){ShopProxy proxy = new ShopProxy() ; //获得代理类Shop shop = (Shop)proxy.bind(new ShopImpl()) ; 通过接口把委托对象与代理对象绑定shop.sale();}}所以,bind()方法里传什么对象都可以了,当然前提还是实现了相同接口才行。如果你不了解反射是很难理解动态的代理过程的,不懂的同学请补习一下。。。
总结
可以看出JDK的代理方式必须依赖接口,如果一个类没有实现相应接口是不可以被代理的。
如果你想既不实现接口又要代理,建议去了解一下CGLIB,CGLIB是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
关于CGLIB我了解的也不是太多,这里就不多说了,感兴趣的朋友请自行搜索相关资料吧。( ̄▽ ̄)~*
关于CGLIB我了解的也不是太多,这里就不多说了,感兴趣的朋友请自行搜索相关资料吧。( ̄▽ ̄)~*
大家互相学习互相进步
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ---------------------- 0 0
- 黑马程序员 学习日记(十)
- 黑马程序员 学习日记(十)
- 黑马程序员 日记(十)
- 黑马程序员--学习日记(十)交通灯管理系统
- 黑马程序员-iOS学习日记(十)Foundation
- 黑马程序员java学习日记十 反射
- 黑马程序员_学习日记十_IO二
- 黑马程序员--【学习日记十】——交通灯管理系统
- 黑马程序员——java学习日记十
- 黑马程序员--学习日记
- 黑马程序员学习日记----多线程(一)
- 黑马程序员学习日记----多线程(二)
- 黑马程序员-学习日记17( GUI )
- 黑马程序员 学习日记(一)
- 黑马程序员 学习日记(二)
- 黑马程序员 学习日记(三)
- 黑马程序员 学习日记(四)
- 黑马程序员 学习日记(五)
- UVA10029- Edit Step Ladders
- ACM模板 Bellman_Ford,单源最短路,图论
- Netty Protobuf C# 通信
- 所有浏览器为啥都带Mozilla
- Android Touch事件传递机制详解 上
- 黑马程序员 学习日记(十)
- 以u-boot为例介绍如何在MDK下调试elf格式文件
- LaTex中使用循环连续绘图的例子
- Cocos2d-x3.2下Lua,UserDefault、Texture的使用
- uboot.bin&zImage.bin编译步骤
- IOS 基于APNS消息推送原理与实现
- TCP 链路重置场景总结
- UVA11297--Census(二维线段树)
- 内存对齐