黑马程序员 学习日记(十)
2014-07-19 17:30
169 查看
----------------------
ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------
ShopImpl.java
ShopProxy.java
ShopTest.java
简单的一个静态代理就实现了。重点在于他们都实现了同一个接口,这样才有相同方法,才能在委托类把对象交给代理类的对象的时候确保执行相同方法,实现代理。但在这之余代理可以更自由的去做其他的事情,这就是代理的好处。你随时可以加一个打折促销的广告,夏季冬季随便换也不影响原出售环节。
要做这样一个代理,那我们就要仔细思考。首先肯定还是要接收一个对象参数,然后要实现此对象的哪个方法,执行方法可能需要参数。这样就一共需要这三个参数。JDK正好为我们提供了一个接口,
InvocationHandler接口:
public interface InvocationHandler {
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
}
参数说明:
Object proxy:指被代理的对象。
Method method:要调用的方法
Object[] args:方法调用时所需要的参数
接口解决了,那么最关键的类呢?关键就在于这个类必须是动态的,如果写死它最终还是一个静态代理。所以这个类必须要在运行时动态创建。实现动态创建类要使用Proxy类。
把上面的代理类稍微改动一下,接口和委托类不用动。
如果你想既不实现接口又要代理,建议去了解一下CGLIB,CGLIB是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
关于CGLIB我了解的也不是太多,这里就不多说了,感兴趣的朋友请自行搜索相关资料吧。( ̄▽ ̄)~*
大家互相学习互相进步
----------------------
ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------
ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------
动态代理
代理是一种设计模式,与现实生活中的代理意思接近。一个类的运行由另一个类去代理运行,这样就可以在目标类的方法运行前后都加入额外的内容去执行,也可以对目标方法的参数进行过滤,委托类与代理类通常存在一个关联。代理设计模式非常有利于程序的管理维护和测试。1.静态代理
shop.javapackage 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 { @Override public void sale() { System.out.println("卖出一件货物。"); } @Override public 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 ; } @Override public void sale() { System.out.println("出售货物之前"); shopImpl.sale(); System.out.println("出售货物之后"); } @Override public 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:方法调用时所需要的参数
接口解决了,那么最关键的类呢?关键就在于这个类必须是动态的,如果写死它最终还是一个静态代理。所以这个类必须要在运行时动态创建。实现动态创建类要使用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) ; } //代理对象执行任意方法都会自动来执行一次这个方法。 @Override public 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我了解的也不是太多,这里就不多说了,感兴趣的朋友请自行搜索相关资料吧。( ̄▽ ̄)~*
大家互相学习互相进步
----------------------
ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------
相关文章推荐
- 黑马程序员Java基础加强9-16学习日记
- 黑马程序员学习日记三
- 黑马程序员张毓庆的学习日记第三篇
- 黑马程序员张毓庆的学习日记第八篇
- 黑马程序员张毓庆的学习日记第七篇
- 黑马程序员Java基础加强1-8学习日记
- 黑马程序员张毓庆的学习日记第十二篇
- 黑马程序员张毓庆学习日记第一篇
- 黑马程序员-------学习日记Java基础 第二天
- 黑马程序员张毓庆的学习日记第十篇
- 黑马程序员学习日记五
- 黑马程序员 网络编程学习日记
- 黑马程序员 IO的学习日记
- 黑马程序员张毓庆的学习日记第二篇
- 黑马程序员 交通灯管理学习日记
- 黑马程序员Java基础加强17-24学习日记
- 黑马程序员Java基础加强49-56学习日记
- 黑马程序员 注解学习日记
- 黑马程序员张毓庆的学习日记第五篇
- 黑马程序员张毓庆的学习日记第十一篇