分享

9.6.1 可用的TargetSource实现类(2)(双数据源交换)

 X的世界 2012-08-06


《Spring揭秘》第9章Spring AOP一世,本章我们详尽剖析了Spring AOP中的各种概念和实现原理,这些概念和实现原理是Spring AOP发布之初就确定的,是整个框架的基础。本节为大家介绍可用的TargetSource实现类。

AD:

9.6.1 可用的TargetSource实现类(2)

我们使用构造方法注入为HotSwappableTargetSource注入了初始的目标对象,之后,就可以在程序中对其进行操作,如代码清单9-42所示。

代码清单9-42 HotSwappableTargetSource使用示例

  1. ...  
  2.  
  3. Object proxy = ctx.getBean("taskProxy");  
  4. Object initTarget = ((Advised)proxy).getTargetSource().getTarget();  
  5.  
  6. HotSwappableTargetSource hotSwapTargetSource = ?  
  7. (HotSwappableTargetSource)ctx.getBean("hotSwapTargetSource");  
  8. Object oldTarget = hotSwapTargetSource.swap(new ITask(){  
  9.     public void execute(TaskExecutionContext ctx) {  
  10.         // 省略  
  11.     }});  
  12. Object newTarget = ((Advised)proxy).getTargetSource().getTarget();  
  13.  
  14. assertSame(initTarget, oldTarget);  
  15. assertNotSame(initTarget,newTarget); 

能最快记起来的使用HotSwappableTargetSource的场景,就是我曾经在2005年使用它解决了双数据源的互换问题:在有两个数据库双机热备的情况下,如果一个数据库挂掉,则将程序迅速地切换到另一个数据库。当时,使用了ThrowsAdvice对数据库相关异常进行捕捉,在捕捉到必要的切换信息后,就调用HotSwappableTargetSource的swap方法使用新的数据源替换旧的数据源,具体详情可以参照我的博客文章《对双数据源互换的实现的改进》(http://darrenwang. blogcn.com/diary,101689446.shtml)。

总之,使用HotSwappableTargetSource,我们可以在任何合适的地方、合适的时机对旧的目标对象进行替换,比如可以在某个拦截器中持有相关HotSwappableTargetSource的引用,一旦满足相应的条件,就可以调用swap方法动态替换新的目标对象,也可以设置一个定时任务,让它也持有一个HotSwappableTargetSource的引用,每隔一段时间就使用新的目标对象置换掉旧的,等等诸如此类的场景。有关HotSwappableTargetSource的使用,还是有待你自己去挖掘吧!

4. CommonsPoolTargetSource

某些时候,我们可能不想每次都返回新的目标对象,而是想返回有限数目的目标对象实例,这些目标对象实例的"地位"是平等的,就好像数据库连接池中的那些Connection一样,我们可以提供一个目标对象的对象池,然后让某个TargetSource实现每次都从这个目标对象池中去取得目标对象。

CommonsPoolTargetSource就是这么一个TargetSource实现,它使用现有的Jakarta Commons Pool提供对象池支持。使用它,跟使用PrototypeTargetSource没什么太大差别,如代码清单9-43所示。

代码清单9-43 CommonsPoolTargetSource使用配置示例

  1. <bean id="target" class="..." singleton="false"/>  
  2.  
  3. <bean id="poolingTargetSource" class="org.
    springframework.aop.target.CommonsPoolTargetSource"
    >  
  4.     <property name="targetBeanName">  
  5.         <value>target</value>  
  6.     </property>  
  7. </bean>  
  8.  
  9. <bean id="targetProxy" class="org.springframework.
    aop.framework.ProxyFactoryBean"
    >  
  10.     <property name="targetSource">  
  11.         <ref bean="poolingTargetSource"/>  
  12.     </property>  
  13.     <property name="interceptorNames">  
  14.         <list>  
  15.             <value>anyInterceptor</value>  
  16.         </list>  
  17.     </property>  
  18. </bean> 

在CommonsPoolTargetSource的使用上,需要注意的问题跟PrototypeTargetSource差不多,即注意它要使用prototype型scope的bean定义。CommonsPoolTargetSource还有许多控制对象池的可配置属性,比如对象池的大小、初始对象数量等,都可以在配置中指定。详情可参照CommonsPool- TargetSource的Javadoc文档。

如果CommonsPoolTargetSource不能满足要求,或者因为其他原因不能使用Jakarta Commons Pool,那么也可以通过扩展org.springframework.aop.target.AbstractPoolingTargetSource类,实现相应的提供对象池化功能的TargetSource。有关扩展AbstractPoolingTargetSource的更多信息,可以参考它的Javadoc或者源码,毕竟Spring是开源的嘛!

5. ThreadLocalTargetSource

如果想为不同的线程调用提供不同的目标对象,那么可以使用org.springframework.aop. target.ThreadLocalTargetSource。它可以保证各自线程上对目标对象的调用,可以被分配到当前线程对应的那个目标对象实例上。其实,ThreadLocalTargetSource无非就是对JDK标准的Thread- Local进行了简单的封装而已。

与其他TargetSource类似,ThreadLocalTargetSource的使用也比较简单,见代码清单9-44。

代码清单9-44 ThreadLocalTargetSource使用配置示例

  1. <bean id="target" class="..." singleton="false"/>  
  2.  
  3. <bean id="threadLocalTargetSource" ?  
  4. class="org.springframework.aop.target.ThreadLocalTargetSource">  
  5.     <property name="targetBeanName">  
  6.         <value>target</value>  
  7.     </property>  
  8. </bean>  
  9.  
  10. <bean id="targetProxy" class="org.springframework.
    aop.framework.ProxyFactoryBean"
    >  
  11.     <property name="targetSource">  
  12.         <ref bean="threadLocalTargetSource"/>  
  13.     </property>  
  14.     <property name="interceptorNames">  
  15.         <list>  
  16.             <value>anyInterceptor</value>  
  17.         </list>  
  18.     </property>  
  19. </bean> 

我想你不会忘记将目标对象的bean定义的scope设置成prototype型吧。毕竟人家每个线程起码得有自己的目标对象实例不是?不过没关系,要是非设置成singleton的,Spring AOP会"给你好看"的啦,呵呵,异常伺候!


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多