Spring @Configuration和FactoryBean

本文探讨了在Spring中将FactoryBean转换为@Configuration样式时遇到的问题。主要焦点在于,当直接调用FactoryBean.getObject()时,会绕过如InitializingBean的'afterPropertiesSet'生命周期方法。解决方案包括保留FactoryBean的生命周期方法或直接在@Configuration中模拟其行为。内容引用了Biju Kunjummen的文章,提供了关于如何正确处理FactoryBean转换的见解。
摘要由CSDN通过智能技术生成
考虑使用FactoryBean通过Spring配置文件定义缓存:
<cache:annotation-driven />
 <context:component-scan base-package='org.bk.samples.cachexml'></context:component-scan>
 
 <bean id='cacheManager' class='org.springframework.cache.support.SimpleCacheManager'>
  <property name='caches'>
   <set>
    <ref bean='defaultCache'/>
   </set>
  </property>
 </bean>
 
 <bean name='defaultCache' class='org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean'>
  <property name='name' value='default'/>
 </bean>

工厂bean ConcurrentMapCacheFactoryBean是一个依次负责创建Cache bean的bean。

我第一次尝试将此设置转换为@Configuration样式:

@Bean
public SimpleCacheManager cacheManager(){
 SimpleCacheManager cacheManager = new SimpleCacheManager();
 List<Cache> caches = new ArrayList<Cache>();
 ConcurrentMapCacheFactoryBean cacheFactoryBean = new ConcurrentMapCacheFactoryBean();
 cacheFactoryBean.setName('default');
 caches.add(cacheFactoryBean.getObject());
 cacheManager.setCaches(caches );
 return cacheManager;
}

但是,这没有用,原因是我在这里完全绕过了一些Spring bean生命周期机制。 事实证明,ConcurrentMapCacheFactoryBean还实现了InitializingBean接口,并在InitializingBean的'afterPropertiesSet'方法中对缓存进行了急切的初始化。 现在,通过直接调用factoryBean.getObject(),我完全绕过了afterPropertiesSet方法。

有两种可能的解决方案:
1.以与在XML中定义的相同方式定义FactoryBean:

@Bean
public SimpleCacheManager cacheManager(){
 SimpleCacheManager cacheManager = new SimpleCacheManager();
 List<Cache> caches = new ArrayList<Cache>();
 caches.add(cacheBean().getObject());
 cacheManager.setCaches(caches );
 return cacheManager;
}

@Bean
public ConcurrentMapCacheFactoryBean cacheBean(){
 ConcurrentMapCacheFactoryBean cacheFactoryBean = new ConcurrentMapCacheFactoryBean();
 cacheFactoryBean.setName('default');
 return cacheFactoryBean;
}

在这种情况下,从@Bean方法返回一个显式的FactoryBean,Spring将负责在此bean上调用生命周期方法。

2.复制相关生命周期方法中的行为,在此特定实例中,我知道FactoryBean在afterPropertiesSet方法中实例化ConcurrentMapCache,我可以通过以下方式直接复制此行为:

@Bean
public SimpleCacheManager cacheManager(){
 SimpleCacheManager cacheManager = new SimpleCacheManager();
 List<Cache> caches = new ArrayList<Cache>();
 caches.add(cacheBean());
 cacheManager.setCaches(caches );
 return cacheManager;
}

@Bean
public Cache  cacheBean(){
 Cache  cache = new ConcurrentMapCache('default');
 return cache;
}

将FactoryBean从xml转换为@Configuration时要记住的一点。

注意:
可以根据需要进行一页有效的测试:

package org.bk.samples.cache;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.equalTo;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Random;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.cache.Cache;
 import org.springframework.cache.annotation.Cacheable;
 import org.springframework.cache.annotation.EnableCaching;
 import org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean;
 import org.springframework.cache.support.SimpleCacheManager;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.stereotype.Component;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
 @RunWith(SpringJUnit4ClassRunner.class)
 @ContextConfiguration(classes={TestSpringCache.TestConfiguration.class})
 public class TestSpringCache {
 
  @Autowired TestService testService;
 
  @Test
  public void testCache() {
   String response1 = testService.cachedMethod('param1', 'param2');
   String response2 = testService.cachedMethod('param1', 'param2');
   assertThat(response2, equalTo(response1));
  }
 
 
  @Configuration
  @EnableCaching
  @ComponentScan('org.bk.samples.cache')
  public static class TestConfiguration{
 
   @Bean
   public SimpleCacheManager cacheManager(){
    SimpleCacheManager cacheManager = new SimpleCacheManager();
    List<Cache> caches = new ArrayList<Cache>();
    caches.add(cacheBean().getObject());
    cacheManager.setCaches(caches );
    return cacheManager;
   }
 
   @Bean
   public ConcurrentMapCacheFactoryBean cacheBean(){
    ConcurrentMapCacheFactoryBean cacheFactoryBean = new ConcurrentMapCacheFactoryBean();
    cacheFactoryBean.setName('default');
    return cacheFactoryBean;
   }
  }
 
 }
 
 interface TestService{
  String cachedMethod(String param1,String param2);
 }
 
 @Component
 class TestServiceImpl implements TestService{
 
  @Cacheable(value='default', key='#p0.concat('-').concat(#p1)')
  public String cachedMethod(String param1, String param2){
   return 'response ' + new Random().nextInt();
  }
 }

参考: all和其他博客中来自我们JCG合作伙伴 Biju Kunjummen的Spring @Configuration和FactoryBean


翻译自: https://www.javacodegeeks.com/2012/08/spring-configuration-and-factorybean.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值