`
hyj_dx
  • 浏览: 100114 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

spring中cache服务的实现(二)

阅读更多

 public Class getTargetClass() {

           try {

                 return this.getTarget().getClass();

           } catch (Exception e) {

                 return null;

           }

      }

}

 

       现在,我们运行测试用例。测试状态条中出现绿条,测试通过。注意,我们在testcache.xml定义的更新数据的间隔是10秒;测试代码每隔2秒读取一次数据;因此我们预计前5次读取的数据是相同的。让我们观察Console窗口中DEBUG信息():

......

BizManager started.

......

27,781 DEBUG unittest.MyBusinessObject - create new MyBusnissObject

......

get id from BizObjec=9

get id from BizObjec=9

get id from BizObjec=9

get id from BizObjec=9

get id from BizObjec=9

37,796 DEBUG unittest.MyBusinessObject - create new MyBusnissObject

get id from BizObjec=59

 

       果然如此,前5次变量id的值都是9,读取第6次数据时,时间已经过12秒,此时变量id的值是59。现在我们将refreshPeriod的值改为5秒,DEBUG信息如下:

BizManager started.

......

get id from BizObjec=9

get id from BizObjec=9

get id from BizObjec=9

03,921 DEBUG unittest.MyBusinessObject - create new MyBusnissObject

get id from BizObjec=39

get id from BizObjec=39

get id from BizObjec=39

 

重构OSCacheTargetSource

       首先定义Cachable接口如下:

 

public interface Cachable {

      public void refresh();

      public void close();

}

 

       然后,让MyBusinessObject实现Cachable接口,refresh方法如下:

public void refresh() {

      logger.debug("refresh MyBusnissObject");

      id = BizManager.getId();

}

 

      接下来,修改OSCacheTargetSource类的getCached方法如下,其中屏蔽的是先前的实现代码:

 

private Object getCached() {

      try {

              //CacheEntry.INDEFINITE_EXPIRY = -1

              target = (Object) admin.getFromCache(MY_KEY, refreshPeriod);

      } catch (NeedsRefreshException nre) {

              try {

                    //target = target.getClass().newInstance();

                    ((Cachable)target).refresh();

                    admin.putInCache(MY_KEY, target);

              } catch (Exception ex) {

                    target = nre.getCacheContent();

                    admin.cancelUpdate(MY_KEY);

              }

       }

       return target;

}

 

       最后,运行测试用例,出现了绿条,测试通过。下面是DEBUG信息输出:

 

BizManager started.

......

47,828 DEBUG base.Cache - No cache entry exists for key='mykey', creating

47,828 DEBUG unittest.MyBusinessObject - refresh MyBusnissObject

......

get id from BizObjec=9

get id from BizObjec=9

get id from BizObjec=9

53,843 DEBUG unittest.MyBusinessObject - refresh MyBusnissObject

get id from BizObjec=39

get id from BizObjec=39

get id from BizObjec=39

 

       我们的方案看来起作用了,但仍然让我们感觉不好,因为需要缓存服务的对象必须要实现Cachable接口,而且OSCacheTargetSource假设需要缓存的对象必须拥有缺省的构造器,这种解决方案太具有侵入性,违反了Spring Framework的设计思想。为了重构代码,OSCacheTargetSource对象必须获得需要缓存的Bean的信息。因此,OSCacheTargetSource对象必须实现BeanFactoryAware或ApplicationContextAware接口。为了证实我们的思路,参考CommonsPoolTargetSource的源代码,发现它确实是实现了BeanFactoryAware接口。

       基于以上的分析,我们把OSCacheTargetSource重构为:

 

public class OSCacheTargetSource implements TargetSource, BeanFactoryAware {

     

      public void setTargetBeanName(String beanName) {

            this.targetBeanName = beanName;

      }

 

      private Object getCached() {

           try {

                 target = (Object) admin.getFromCache(MY_KEY, refreshPeriod);

           } catch (NeedsRefreshException nre) {

                 try {

                       target = beanFactory.getBean(this.targetBeanName);

                       admin.putInCache(MY_KEY, target);

                 } catch (Exception ex) {

                       target = nre.getCacheContent();

                       admin.cancelUpdate(MY_KEY);

                 }

           }

           return target;

      }

}

 

       将MyBusinessObject重构为:

 

public class MyBusinessObject implements Business {

        final Log logger = LogFactory.getLog(this.getClass());

        private int id = 0;

 

        public MyBusinessObject() {

             logger.debug("create new MyBusnissObject");

             id = BizManager.getId();

        }

 

        public int getId() {

             return id;

        }

 

        public void close() {}

}

 

      并修改testcache.xml配置文件如下:

 

<beans>

       <bean id="businessObjectTarget" class="unittest.MyBusinessObject" singleton="false" destroy-method="close"/>

       <bean id="cacheTargetSource" class="unittest.OSCacheTargetSource">

             <property name="targetBeanName"><value>businessObjectTarget</value></property>

             <property name="refreshPeriod"><value>10</value></property>

       </bean>

       <bean id="businessObject" class="org.springframework.aop.framework.ProxyFactoryBean">

             <property name="proxyInterfaces"><value>unittest.Business</value></property>

             <property name="targetSource"><ref local="cacheTargetSource"/></property>

       </bean>

</beans>

 

       现在,我们运行测试用例。测试状态条中出现绿条,测试通过。但注意到OSCacheTargetSource类中缓存的对象的key值仍然是写死的,我们需要一个这样的key值,对于BeanFactory或ApplicationContext必须是唯一的。因为每个Bean的id值正好符合这个条件,我们可以使用targetBeanName作为key值。因此OSCacheTargetSource类修改为:

 

private Object getCached() {

      try {

            target = (Object) admin.getFromCache(

            this.targetBeanName, refreshPeriod);

      } catch (NeedsRefreshException nre) {

            try {

                   target = beanFactory.getBean(this.targetBeanName);

                   admin.putInCache(this.targetBeanName, target);

            } catch (Exception ex) {

                   target = nre.getCacheContent();

                   admin.cancelUpdate(this.targetBeanName);

            }

       }

       return target;

}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics