walterwing
日历
<
2008年7月
>
日
一
二
三
四
五
六
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
统计
随笔 - 12
文章 - 1
评论 - 7
引用 - 0
导航
BlogJava
首页
发新随笔
发新文章
联系
聚合
管理
常用链接
我的随笔
我的评论
我的参与
最新评论
留言簿
(1)
给我留言
查看公开留言
查看私人留言
随笔分类
Java基础(9)
(rss)
大千世界(2)
(rss)
随笔档案
2009年2月 (2)
2008年11月 (2)
2008年10月 (2)
2008年7月 (7)
搜索
最新评论
1. re: java线程基本知识小结
very good
--very good
2. re: (转载)高科技公司的摇篮 — 斯坦福大学[未登录]
@与你同飞
面包会有的:) 虽然有生之年可能看不到国内大学也能跻身世界前列,但我们也要对自己有信心,哪怕路途再遥远,也要努力向前
--Wing
3. re: (转载)高科技公司的摇篮 — 斯坦福大学
差距啊,差距,什么是差距?这就是差距!
--与你同飞
4. re: 一道小而精巧的笔试题——Set、equals、类型转换……
评论内容较长,点击标题查看
--This is Wing
5. re: 一道小而精巧的笔试题——Set、equals、类型转换……
请讲讲
removeEntryForKey
这段代码吧,
我是新手,看不懂。
--sclsch
阅读排行榜
1. 对象的序列化和反序列化(转载+原创)(4889)
2. java线程基本知识小结(3350)
3. (转载)高科技公司的摇篮 — 斯坦福大学(642)
4. 一道小而精巧的笔试题——Set、equals、类型转换……(639)
5. The Collections Framework (摘要)- Part 4(557)
评论排行榜
1. 一道小而精巧的笔试题——Set、equals、类型转换……(3)
2. (转载)高科技公司的摇篮 — 斯坦福大学(2)
3. java线程基本知识小结(1)
4. 静态Proxy与动态Proxy用法浅析(0)
5. The Collections Framework (摘要)- Part 4(0)
静态Proxy与动态Proxy用法浅析
今天读了读夏昕写的《Spring开发指南》,在“AOP in Spring”一节,作者讲述了Spring中如何通过动态AOP来提供内置的AOP支持。“从技术角度来讲,所谓动态AOP,即通过动态Proxy模式,在目标对象的方法调用前后插入相应的处理代码”
作者举了一些例子来解释何为静态Proxy,何为动态Proxy。奈何我根基尚浅,最作者举的动态Proxy的例子懵懂不解,于是自己尝试着摸索一番,终于对动态Proxy的用法有了一个初步的认识。
首先还是来看静态Proxy,就我目前的认识看来,Proxy的主要用途是对类中方法的执行进行一下包装,在方法执行之前,或之后,或both,加入一些“额外”的操作。典型的应用就是加入事务处理。
静态Proxy相对来讲比较简单,它是对上面所述思想的一个最直接的实现。
假设我们现在有如下一个接口:
package
aop;
public
interface
Foo
{
public
String getMessage(String arg);
}
以及该接口的一个实现类:
package
aop;
public
class
FooImpl
implements
Foo
{
public
String getMessage(String arg)
{
return
"
hi
"
+
arg;
}
}
那么很容易,我们可以通过如下方式进行调用:
package
aop;
public
class
Test
{
/** */
/**
*
@param
args
*/
public
static
void
main(String[] args)
{
Foo foo
=
new
FooImpl();
String message
=
foo.getMessage(
"
Wing
"
);
System.out.println(message);
}
}
输出结果:
hi Wing
现在问题来了:如果现在我们想在getMessage()之外添加一些额外的操作,比如在这之前输出“Begin”,在之后输出“done”,但又不能改变原有接口,怎么办?也很简单,用静态Proxy就可以很方便的实现:
package
aop;
public
class
StaticProxy implements Foo
{
private
Foo foo;
public
StaticProxy(Foo foo)
{
this
.foo
=
foo;
}
public
void
getMessage(String arg)
{
System.out.println(
"
Begin!
"
);
String message
=
foo.getMessage(arg);
System.out.println(message);
System.out.println(
"
Done!
"
);
}
}
调用:
package
aop;
public
class
TestStaticProxy
{
/** */
/**
*
@param
args
*/
public
static
void
main(String[] args)
{
Foo foo
=
new
StaticProxy(
new
FooImpl());
foo.getMessage(
"
Wing
"
);
}
}
结果:
Begin
!
hi Wing
Done
!
你可以看到,StaticProxy只是在Foo的某实现类基础上包了一层,当然我们这里加的两个输出语句无足轻重,但如果我们把这两个输出语句替换成事务处理,意义就大不一样了。
可见,通过静态Proxy可以实现我们的需求,但如果我们有十几、二十个这样的接口实现类,需要类似的处理,我们怎么办?难道每个实现类都对应一个Proxy吗?
这时,我们就需要动态Proxy:
package
aop;
import
java.lang.reflect.InvocationHandler;
import
java.lang.reflect.Method;
import
java.lang.reflect.Proxy;
public
class
AOPHandler
implements
InvocationHandler
{
private
Object orginal;
public
Object bind(Object obj)
{
orginal
=
obj;
return
Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
this
);
}
public
Object invoke(Object proxy, Method method, Object[] args)
throws
Throwable
{
System.out.println(
"
Begin!
"
);
Object result
=
method.invoke(orginal, args);
System.out.println(result);
System.out.println(
"
Done!
"
);
return
result;
}
}
第一次看到上面的代码肯定不知所以,稍后解释,我们先看如何调用:
package
aop;
public
class
TestAOP
{
/** */
/**
*
@param
args
*/
public
static
void
main(String[] args)
{
AOPHandler handler
=
new
AOPHandler();
Object proxy
=
handler.bind(
new
FooImpl());
String message
=
((Foo) proxy).getMessage(
"
Wing
"
);
System.out.println(message);
}
}
结果:
Begin
!
hi Wing
Done
!
hi Wing
下面来解释一下AOPHandler这个类:
首先,bind()方法是用来创建动态Proxy实例。动态Proxy也是Proxy,和静态Proxy一样,功能上都是为了在调用某接口实现类的方法之余,添加一些额外的操作(比如事务处理),他们(动态和静态Proxy)都是一种特殊的接口实现类。因此,我们在调用的时候可以用
String message = ((Foo) proxy).getMessage("Wing");
把proxy实例直接cast为Foo类型,并调用foo接口上的方法。
不同的是,静态Proxy,正如前面看到的,是直接实现了接口,并在接口的方法中直接调用该接口某实现类对应的方法。而动态Proxy,是利用Java.lang.reflect.Proxy类提供的这样一种机制:当构建Proxy时,我们需要提供接口,以及一个关联的调用处理程序对象(通常实现了InvocationHandler接口),当我们在Proxy上调用接口上的方法(任意方法)时,将触发调用InvocationHandler接口定义的invoke()方法,由invoke方法完成相应的操作。
上面的AOPHandler类,是将动态Proxy的构建与InvocationHandler接口的实现结合在了一起。
通过AOPHandler,我们可以在运行时期动态的决定用哪个接口实现类来创建Proxy,而不需事先为每个实现类定义对应的Proxy,灵活性和复用性大大增强。
进一步的,我们可以利用java反射机制,通过类名来得到接口实现类的实例,进而得到该实例的动态Proxy。这样我们就可以在配置文件里动态指定需要用到的接口实现类,就像Spring中所做的一样。
posted on 2008-07-09 15:08
This is Wing
阅读(413)
评论(0)
编辑
收藏
所属分类:
Java基础
新用户注册
刷新评论列表
只有注册用户
登录
后才能发表评论。
网站导航:
博客园
IT新闻
Chat2DB
C++博客
博问
管理
相关文章:
垃圾回收(转载)
一道小而精巧的笔试题——Set、equals、类型转换……
对象的序列化和反序列化(转载+原创)
java线程基本知识小结
静态Proxy与动态Proxy用法浅析
The Collections Framework (摘要)- Part 4
The Collections Framework (摘要)- Part 3
The Collections Framework (摘要)- Part 2
The Collections Framework (摘要)- Part 1
Copyright © This is Wing
Powered by:
博客园
模板提供:
沪江博客