Java 代理之动态代理 (续前)
2016-06-15 17:02
411 查看
...续前一篇
二、动态代理
动态代理与静态代理相相比,最大的好处就是接口中声明的所有方法都被转移到一个集中的方法中进行处理(即 invoke 方法)。这样做的好处是,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样,在每一个方法里都进行中转。
但是,动态代理类只能代理接口,代理类都需要实现 InvocationHandler 类,并覆写其 invoke() 方法。该invoke() 方法就是所有方法被代理后需要调用的方法,该 invoke() 方法返回的值是被代理接口的一个实现类。
还是以前面的服务生例子为例,创建以下动态代理类:
/**
* 服务员动态代理类
*
* @author ZHULX
*
*/
public
class DynamicProxyWaiter implements InvocationHandler {
// 持有被代理的接口对象
private Object
waiter;
/**
* 绑定被代理的对象,也就是关联到哪个接口(与具体的实现类绑定)的哪些方法被调用时,执行 invoke
方法。
*
* @param waiter
* 被代理的实现类对象
* @return返回代理后的对象
*/
public ObjectbindRelation(Object
waiter) {
<
d113
p> this.waiter =
waiter;
ObjectproxyWaiter = Proxy.newProxyInstance(waiter.getClass().getClassLoader(),waiter.getClass().getInterfaces(),this);
return
proxyWaiter;
}
/**
* 所有方法的代理方法
*
* @param proxy
* 代理后的对象
* @param method
* 被代理对象即将被调用的方法
* @param args
* 即将被调用方法的参数
* @return返回执行后的代理对象
*/
@Override
public Object invoke(Object
proxy, Method method, Object[]
args) throws Throwable {
Objectresult =
waiter;
if (method.getName().endsWith("Welcome")) {
System.out.println("******
向顾客行90°度鞠躬礼 ******");
result =
method.invoke(waiter,
args);
}else
if (method.getName().endsWith("Goodbye")) {
System.out.println("******
向顾客行45°度鞠躬礼 ******");
result =
method.invoke(waiter,
args);
}
return
result;
}
}
最后,我再重新创建一个测试类:
/**
* 测试类
*
* @author ZHULX
*
*/
public
class Test {
public
static void main(String[]
args) {
// 被代理的对象
IWaiterwaiter = new WaiterImpl();
System.out.println("未代理前的执行结果:");
waiter.sayWelcome();
waiter.sayGoodbye();
// 代理对象
DynamicProxyWaiterhandler =
new DynamicProxyWaiter();
IWaiterproxyWaiter = (IWaiter)
handler.bindRelation(waiter);
// 执行代理对象的方法
System.out.println("\n代理后的执行结果:");
proxyWaiter.sayWelcome();
proxyWaiter.sayGoodbye();
}
}
如果一切正常,输出应该如下所示:
未代理前的执行结果:
****** 您好,欢迎光临! ******
****** 您慢走,欢迎再次光临! ******
代理后的执行结果:
****** 向顾客行90°度鞠躬礼 ******
****** 您好,欢迎光临! ******
****** 向顾客行45°度鞠躬礼 ******
****** 您慢走,欢迎再次光临! ******
因此,不难发现,我们可以灵活地在委托类执行某方法前后加入任意的程序逻辑。
二、动态代理
动态代理与静态代理相相比,最大的好处就是接口中声明的所有方法都被转移到一个集中的方法中进行处理(即 invoke 方法)。这样做的好处是,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样,在每一个方法里都进行中转。
但是,动态代理类只能代理接口,代理类都需要实现 InvocationHandler 类,并覆写其 invoke() 方法。该invoke() 方法就是所有方法被代理后需要调用的方法,该 invoke() 方法返回的值是被代理接口的一个实现类。
还是以前面的服务生例子为例,创建以下动态代理类:
/**
* 服务员动态代理类
*
* @author ZHULX
*
*/
public
class DynamicProxyWaiter implements InvocationHandler {
// 持有被代理的接口对象
private Object
waiter;
/**
* 绑定被代理的对象,也就是关联到哪个接口(与具体的实现类绑定)的哪些方法被调用时,执行 invoke
方法。
*
* @param waiter
* 被代理的实现类对象
* @return返回代理后的对象
*/
public ObjectbindRelation(Object
waiter) {
<
d113
p> this.waiter =
waiter;
ObjectproxyWaiter = Proxy.newProxyInstance(waiter.getClass().getClassLoader(),waiter.getClass().getInterfaces(),this);
return
proxyWaiter;
}
/**
* 所有方法的代理方法
*
* @param proxy
* 代理后的对象
* @param method
* 被代理对象即将被调用的方法
* @param args
* 即将被调用方法的参数
* @return返回执行后的代理对象
*/
@Override
public Object invoke(Object
proxy, Method method, Object[]
args) throws Throwable {
Objectresult =
waiter;
if (method.getName().endsWith("Welcome")) {
System.out.println("******
向顾客行90°度鞠躬礼 ******");
result =
method.invoke(waiter,
args);
}else
if (method.getName().endsWith("Goodbye")) {
System.out.println("******
向顾客行45°度鞠躬礼 ******");
result =
method.invoke(waiter,
args);
}
return
result;
}
}
最后,我再重新创建一个测试类:
/**
* 测试类
*
* @author ZHULX
*
*/
public
class Test {
public
static void main(String[]
args) {
// 被代理的对象
IWaiterwaiter = new WaiterImpl();
System.out.println("未代理前的执行结果:");
waiter.sayWelcome();
waiter.sayGoodbye();
// 代理对象
DynamicProxyWaiterhandler =
new DynamicProxyWaiter();
IWaiterproxyWaiter = (IWaiter)
handler.bindRelation(waiter);
// 执行代理对象的方法
System.out.println("\n代理后的执行结果:");
proxyWaiter.sayWelcome();
proxyWaiter.sayGoodbye();
}
}
如果一切正常,输出应该如下所示:
未代理前的执行结果:
****** 您好,欢迎光临! ******
****** 您慢走,欢迎再次光临! ******
代理后的执行结果:
****** 向顾客行90°度鞠躬礼 ******
****** 您好,欢迎光临! ******
****** 向顾客行45°度鞠躬礼 ******
****** 您慢走,欢迎再次光临! ******
因此,不难发现,我们可以灵活地在委托类执行某方法前后加入任意的程序逻辑。
相关文章推荐
- 如何保护Java程序 防止Java反编译
- Java 自动装箱和自动拆箱注意的问题
- spring整合mybatis
- Spring设置定时器:quartz
- 说说Spring中的WebDataBinder
- java导入cer证书
- myEclipse常用快捷键
- spring task定时器的运用
- java学习--面向对象
- 浅析java中间件
- spring.xml MalformedByteSequenceException: 3 字节的 UTF-8 序列的字节 3 无效。
- java调用.net(c#) dll(利用jacob)
- eclipse maven中的jetty插件启动报错
- java根据经纬度坐标计算两点的距离算法
- JAVA File类
- Spring Boot 打开jsp页面 乱码解决方法
- Java Iterator, ListIterator 和 foreach语句使用
- java web开发知识(一)
- java推荐使用枚举定义常量
- Eclipse IDE 使用技巧 (Eclipse工作空间小技巧)(自己的一些学习笔记和心得,记录下来,备忘录和复习使用)