Spring系列(2)--为什么需要动态代理
2011-08-11 20:21
197 查看
前一篇我把我自己实现动态包装的工厂类实现贴了出来,这一篇就来讲讲为什么要进行动态的代理。
理由看起来有以下几点:
1、有的时候我们需要为一些类的方法增加一些额外的责任,因为这些责任是额外的,去改动这些类当然是不好的。
对于这点,大家可以很快的想到用装饰模式或者代理模式去实现。当然,如果责任固定,而且是事先可预料的,可以在代码中预先进行处理,例如增加一个
框架型方法。不过这样一来,一是很难变化,而是使得与框架性方法的拥有者过度耦合,更不现实。
2、需要增加的额外责任不固定,而且需要增加额外责任的类本身也不固定。
虽然采用装饰或者代理(继承代理)模式,可以满足部分要求,但对于需要增加的额外责任不固定,又使得采用装饰模式和代理模式不太适合;而且如果需要增加责任的目标类本身也不固定,那么采用传统的方式,一个个的去写代理或装饰类就不太现实。
3、最关键的我们还希望在类的方法执行的时候,我们能与之有些互动
要实现这点,简单的代理或装饰是很难的了。
要满足上面几点的需求,不会很简单,但我们可以分析一下,我们的要求可以分为三个部分,一是增加额外责任,二是执行期间的交互,三是无缝透明化,也就是目标类能够应用的地方,我们的代理或装饰类也能够用,而且不需要任何额外的改装。我们先看一下二,因为如果二能够实现,增加额外的责任就很容易了,我们完全可以在交互过程中将这个责任委托给外部的对象来完成,这样不仅可以简化代理或装饰类,还使得责任的增加与代理或装饰类分离,在这种情况下,我们的代理类其实就只负责切入来监视(或者HOOK)目标方法,责任更加单一,方法更加简单,这样有利于这种代理类的动态生成。那么怎么实现交互呢,用命令模式是一个选择,但虽然说可以实现,但在代理类和附加责任类之间增加了一个命令层,有两个不利的地方,一是需要增加很多命令类,二是增加了通信里程。在前面的设计模式中我们分析过,命令模式一种更简洁的替代方法就是采用委托来实现,这里我们就采用委托或者事件来处理交互,就是代理类在执行目标方法期间通过委托与附加责任的对象进行交互。对于第三点,如果要做到无缝透明化,那么代理类或者装饰类就只能是目标类的子类了,因为面向对象编程中的继承一个最基本的法则就是父类可以应用的地方,子类都可以应用。二和三解决了,而一可以在交互过程中委托给外部对象实现,那么我们的三个要求都可以实现。我们的目的是为目标类增加额外的责任,通过交互,可以增加的责任也可以很多,从这个视角,很难有个明确的分类。那么我们就回到代理或装饰类的代理方法上,看看我们能够在哪些地方进行切入,能做哪些事情。下面的示意代码是一个典型的代理方法的代码形式:
A;
try
{
B;
Target.DoSomthing()//这里很关键,我们并不是直接执行基类的办法(虽然说也可以),而是调用代理类中目标类的一个引用的目标方法,这样做的目的就是尽量减轻代理类的责任,使得对于目标类与代理类的在创建上分离,在使用上也分离(因为并不是所有的情况都需要这种代理或者监视),代理类的责任更加单一。
C;
}
catch
{
D;
}
finally
{
E;
}
从上面可以看出,代理方法能够做的事情就是在执行目标方法前后增加一些责任。我们能够切入的点也就只有A-E5个点,其中A和B可以阻止目标方法的执行。我们对上面的代码再改进一下,如下:
try
{
A;//在目标方法执行前执行,但不干涉目标方法执行(当然,如果该方法执行中出现异常另当别论)
if(B1==true) //B1:这些交互结果会决定目标方法是否执行,但这些交互方法如何影响结果,是一票否决还是投票制,可根据自己需要决定,比较简单的当然是一票否决制。
{
B2,//在目标方法执行前执行,但是是在B1执行通过后后执行。
var theRet = Target.DoSomthing()
C1;//成功执行之后执行.
Return theRet;
}
C2;//这个点可以不要,放在A一起也可以。这个点是可以简化的.
}
catch
{
D;//异常处理交互处.
}
finally
{
E;//无论成功是否都要进行的交互.
}
能够切入的点就细分成7个,这当然很好,但可能有些复杂了,不过还是能胜任,这种细分,至少比Spring目前提供的切入点要细致些。搞清了切入点,我们就可以利用这个切入点来分类可以增加的额外责任。对于用户来说,就可以知道增加的责任可以在什么时机执行。
现在我们知道,我们可以用代理或装饰类来实现我们的需求,那么为什么要动态代理类呢?原因非常简单,就是我们懒,那么多不可预期的装饰或者代理类形式都差不多,虽然可以批量写,但这么多的类文件要维护本身就是一个麻烦的事情。能够动态的产生这些类,让计算机本身去管理这些类,当然更好。而且是现实的,可以实现的。前面1篇我们已经把实现动态代理的方法实现了。
这一篇我们还知道了这种增加额外责任和交互的方法,就是使用委托,下一篇,我们就来看看如何更好的去实现这种交互。
理由看起来有以下几点:
1、有的时候我们需要为一些类的方法增加一些额外的责任,因为这些责任是额外的,去改动这些类当然是不好的。
对于这点,大家可以很快的想到用装饰模式或者代理模式去实现。当然,如果责任固定,而且是事先可预料的,可以在代码中预先进行处理,例如增加一个
框架型方法。不过这样一来,一是很难变化,而是使得与框架性方法的拥有者过度耦合,更不现实。
2、需要增加的额外责任不固定,而且需要增加额外责任的类本身也不固定。
虽然采用装饰或者代理(继承代理)模式,可以满足部分要求,但对于需要增加的额外责任不固定,又使得采用装饰模式和代理模式不太适合;而且如果需要增加责任的目标类本身也不固定,那么采用传统的方式,一个个的去写代理或装饰类就不太现实。
3、最关键的我们还希望在类的方法执行的时候,我们能与之有些互动
要实现这点,简单的代理或装饰是很难的了。
要满足上面几点的需求,不会很简单,但我们可以分析一下,我们的要求可以分为三个部分,一是增加额外责任,二是执行期间的交互,三是无缝透明化,也就是目标类能够应用的地方,我们的代理或装饰类也能够用,而且不需要任何额外的改装。我们先看一下二,因为如果二能够实现,增加额外的责任就很容易了,我们完全可以在交互过程中将这个责任委托给外部的对象来完成,这样不仅可以简化代理或装饰类,还使得责任的增加与代理或装饰类分离,在这种情况下,我们的代理类其实就只负责切入来监视(或者HOOK)目标方法,责任更加单一,方法更加简单,这样有利于这种代理类的动态生成。那么怎么实现交互呢,用命令模式是一个选择,但虽然说可以实现,但在代理类和附加责任类之间增加了一个命令层,有两个不利的地方,一是需要增加很多命令类,二是增加了通信里程。在前面的设计模式中我们分析过,命令模式一种更简洁的替代方法就是采用委托来实现,这里我们就采用委托或者事件来处理交互,就是代理类在执行目标方法期间通过委托与附加责任的对象进行交互。对于第三点,如果要做到无缝透明化,那么代理类或者装饰类就只能是目标类的子类了,因为面向对象编程中的继承一个最基本的法则就是父类可以应用的地方,子类都可以应用。二和三解决了,而一可以在交互过程中委托给外部对象实现,那么我们的三个要求都可以实现。我们的目的是为目标类增加额外的责任,通过交互,可以增加的责任也可以很多,从这个视角,很难有个明确的分类。那么我们就回到代理或装饰类的代理方法上,看看我们能够在哪些地方进行切入,能做哪些事情。下面的示意代码是一个典型的代理方法的代码形式:
A;
try
{
B;
Target.DoSomthing()//这里很关键,我们并不是直接执行基类的办法(虽然说也可以),而是调用代理类中目标类的一个引用的目标方法,这样做的目的就是尽量减轻代理类的责任,使得对于目标类与代理类的在创建上分离,在使用上也分离(因为并不是所有的情况都需要这种代理或者监视),代理类的责任更加单一。
C;
}
catch
{
D;
}
finally
{
E;
}
从上面可以看出,代理方法能够做的事情就是在执行目标方法前后增加一些责任。我们能够切入的点也就只有A-E5个点,其中A和B可以阻止目标方法的执行。我们对上面的代码再改进一下,如下:
try
{
A;//在目标方法执行前执行,但不干涉目标方法执行(当然,如果该方法执行中出现异常另当别论)
if(B1==true) //B1:这些交互结果会决定目标方法是否执行,但这些交互方法如何影响结果,是一票否决还是投票制,可根据自己需要决定,比较简单的当然是一票否决制。
{
B2,//在目标方法执行前执行,但是是在B1执行通过后后执行。
var theRet = Target.DoSomthing()
C1;//成功执行之后执行.
Return theRet;
}
C2;//这个点可以不要,放在A一起也可以。这个点是可以简化的.
}
catch
{
D;//异常处理交互处.
}
finally
{
E;//无论成功是否都要进行的交互.
}
能够切入的点就细分成7个,这当然很好,但可能有些复杂了,不过还是能胜任,这种细分,至少比Spring目前提供的切入点要细致些。搞清了切入点,我们就可以利用这个切入点来分类可以增加的额外责任。对于用户来说,就可以知道增加的责任可以在什么时机执行。
现在我们知道,我们可以用代理或装饰类来实现我们的需求,那么为什么要动态代理类呢?原因非常简单,就是我们懒,那么多不可预期的装饰或者代理类形式都差不多,虽然可以批量写,但这么多的类文件要维护本身就是一个麻烦的事情。能够动态的产生这些类,让计算机本身去管理这些类,当然更好。而且是现实的,可以实现的。前面1篇我们已经把实现动态代理的方法实现了。
这一篇我们还知道了这种增加额外责任和交互的方法,就是使用委托,下一篇,我们就来看看如何更好的去实现这种交互。
相关文章推荐
- Spring系列(2)--为什么需要动态代理
- Spring系列(2)--为什么需要动态代理
- Spring aop 基于JDK动态代理和CGLIB代理的原理以及为什么JDK代理需要基于接口
- Spring深度系列-java的动态代理机制详解
- 为什么SpringAOP使用JDK动态代理时好像没有代理Object.[equals()、hashCode()、toString()]这三个方法
- JDK动态代理干了什么事情?为什么我的事务会不起效?spring的事务到底应该怎么使用?原理是什么?
- jdk的动态代理及为什么需要接口
- Spring系列之 (十一):AOP实现方式:动态代理的两个方式(JDK和Cglib)
- 关于使用spring的动态代理机制时为什么必须指定接口
- Spring笔记(三)AOP前篇之动态代理
- 反射实现 AOP 动态代理模式(Spring AOP实现原理)
- 做一些Spring AOP做过的事,封装 jdk动态代理成为一个黑盒子
- Spring学习总结——静态代理、JDK与CGLIB动态代理、AOP+IoC
- Spring AOP注解失效的坑及JDK动态代理
- spring aop学习8:spring对jdk和cglib动态代理的选择
- jdk动态代理,spring核心动态代理
- Spring学习——jdk动态代理例子
- JAVA的动态代理机制及Spring的实现方式
- 为什么需要Spring?----理解SSH框架中的Spring (2012-10-26 11:23:09)
- Spring动态代理(一)