老妖的博客
现实的中没有几个人能够真为对方去死,甚至山盟海誓很快就会在金钱面前变的微不足道,这才是生活。没有永远的爱,除了你的父母对你,当然也就没有永远的恨,更没有永远的痛,时间是最好的治疗大师,它会很快抚平你心灵上累累的伤痕。很多年以后你想起来时,那些在你生命中汹涌来往的人群至多是个模糊的影子或者毫无意义的名字
posts - 105,  comments - 171,  trackbacks - 0
Everyone using spring is aware of the easy to handle ApplicationContext of Spring. There you define all your beans inside an XML and you can use them as AOP targets or plain javabeans. But what if you have AOP targets that are not known on Spring startup because they reside in a DB or some other storage. IMO there are two ways you can go:
  • Code something like a PropertyPlaceHolderConfigurer but acting on a Database, resulting in a DBPropertyPlaceholderConfigurer. The problem with this approach is that you dont have any datasource definitions at this point and it will be tricky to get it work this way.
  • The other approach is using a HotSwappableTargetSource as target of your ProxyFactoryBean. Here you simply code a DummyImplementation of the desired interface and replace the dummy on startup with the real implementation from the database or from whereever you want via reflection.
I decide to use the HotSwappable direction to achieve the overall goal.
example ApplicationContext definition
 1 <bean id="erpDataCollectorTarget" class="de.logentis.DummyERPDataCollector">
 2    <property name="clientManagerService" ref="clientManagerService"/>
 3    <property name="erpDataSource" ref="erpDataSource"/>
 4  </bean>
 5 <bean id="swapper" class="org.springframework.aop.target.HotSwappableTargetSource">
 6    <constructor-arg ref="erpDataCollectorTarget"/>
 7 </bean><bean id="erpDataCollector" class="org.springframework.aop.framework.ProxyFactoryBean">
 8     <property name="targetSource" ref="swapper"/>
 9     <property name="proxyInterfaces" value="de.logentis.ERPDataCollector"/>
10     <property name="interceptorNames">
11       <list>
12          <value>jdoTransactionInterceptor</value>
13       </list>
14     </property>
15 </bean>

Look at the erpDataCollector bean, its a transactional proxy in my scenario. But as you can see, i dont use the "target" attribute with a concrete and not changeable bean definition but a "targetSource" pointing to a HotSwappableTargetSource. This hotswappable things get a default implementation which is nothing more than an empty implementation of the ERPDataCollector interface.

Now when my application starts up, the internal spring plumbing comes first, after that i have a section where i setup my application with various defaults and other stuff. Somewhere in that section, i am doing this:

1 // get the swapper bean from the Context, not shown here
2 HotSwappableTargetSource swapper = getFromContext();
3 // get the user defined class name from DB
4 String classToLoad = getClassNameFromDB();
5 Object o = getInstanceFromClassName(classToLoad);// swap the instances, removes the dummy and put the real impl
6 // oldObject is the dummy and will be returned, normally you dont need
7 // it anymore, but you can printout to be sure that it works like exptected
8 Object oldObject = swapper.swap(o);

At this point, the dummy is replaced with the class from the DB. Of course the DB holds only the full name of the class and it will get loaded via reflection. I left that out because this is plain java programming. Retrieving the swapper from the applicationContext is also trivial. One way would be to put this very code inside a bean which is controlled by Spring, this way you can just define a setter for the swapper and add the needed XML definition for that bean. If you run this from a ServletContextListener (best way to place bootstrap code), you can use something like this.
do Hotswapping in ServletContextListener

 1 public class ApplicationInitFilter implements ServletContextListener {    public void contextInitialized(ServletContextEvent event) {
 2         WebApplicationContext webAppContext =
 3                WebApplicationContextUtils.getWebApplicationContext(
 4                                     event.getServletContext());        HotSwappableTargetSource swapper = 
 5                (HotSwappableTargetSource)webAppContext.getBean("swapper");        String classToLoad = getClassNameFromDB();
 6         Object o = getInstanceFromClassName(classToLoad);
 7         Object oldObject = swapper.swap(o);
 8     }    public void contextDestroyed(ServletContextEvent event) {
 9       // empty impl
10     }}

The interessting thing is, you can program an admin frontend for defining classes like this (its a german screenshot, but it should be readable for everyone): http://www.logemann.org/divs/dynclassdef.gif

All in all, you can see that i used the HotSwappableTargetSource in a slightly different way than its used to be. I think the inventors created this class mainly to switch from one "real" implementation to another. In our context, we are switching from a dummy implementation to the real one but technically its the same of course. Thanks to Daniel Potter from the Spring community for mentioning the HotSwappable class, this really speeded up in finding my overall solution.

posted on 2005-11-09 16:50 老妖 阅读(994) 评论(0)  编辑  收藏 所属分类: spring

只有注册用户登录后才能发表评论。


网站导航:
 

<2005年11月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

常用链接

随笔分类(48)

随笔档案(104)

好友链接

我的豆瓣

积分与排名

  • 积分 - 219755
  • 排名 - 257

最新评论

阅读排行榜