henry1451 的专栏
BlogJava
首页
新随笔
新文章
联系
聚合
管理
posts - 60,comments - 71,trackbacks - 0
<
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
常用链接
我的随笔
我的评论
我的参与
最新评论
留言簿
(6)
给我留言
查看公开留言
查看私人留言
我参与的团队
架构师之家(0/0)
随笔档案
2009年9月 (1)
2009年6月 (1)
2009年5月 (2)
2009年4月 (3)
2009年3月 (2)
2009年1月 (1)
2008年12月 (3)
2008年11月 (2)
2008年10月 (3)
2008年9月 (7)
2008年8月 (9)
2008年7月 (23)
2008年6月 (1)
2008年5月 (2)
文章分类
Hibernate技术(5)
Java技术(15)
Jsp,Js,Ajax,Html技术(8)
Linux技术(2)
Oracle技术(9)
Spring技术
Struts,Webwork,Xwork技术(3)
其他相关(1)
开源技术(7)
文章档案
2008年6月 (27)
2008年5月 (27)
2008年4月 (3)
博客集锦
hk2000c技术专栏
即兴的灵感
和风细雨
小方的Java博客
小飞龙
急死我了
每日一得
资源与技术网站
BlogJava热点分类
BlogJava随笔
JavaEye
J道
Matrix
Open-open
SourceForge
搜索
最新评论
1. re: 关于关闭Connection是否会自动关闭Statement,ResultSet问题
谢了, 很受用!
--码农C
2. re: ClientAbortException 异常解决办法
换浏览器后可以了
--换浏览器后可以了
3. re: eclipse 下环境变量设置[未登录]
请问 MAVEN_REPO在哪定义的?
--a
4. re: 图形统计工具amCharts体验
无语
--EE
5. re: ClientAbortException 异常解决办法
。。。。。。。
--q
阅读排行榜
1. ClientAbortException 异常解决办法(14156)
2. Eclipse下安装TomcatPlugin插件(8429)
3. 图形统计工具amCharts体验(6254)
4. PL/pgSQL - SQL过程语言(转)(5570)
5. 如何修改存储过程(4481)
评论排行榜
1. 取得单选按钮中显示的内容(9)
2. ClientAbortException 异常解决办法(7)
3. 图形统计工具amCharts体验(4)
4. 10.1快乐!(4)
5. 重复提交、重复刷新、防止后退的问题以及处理方式(转)(4)
静态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-10 16:07
henry1451
阅读(316)
评论(0)
编辑
收藏
新用户注册
刷新评论列表
只有注册用户
登录
后才能发表评论。
网站导航:
博客园
IT新闻
知识库
C++博客
博问
管理