2014-06-26 47 views
1

我想实现CommonsPoolTargetSource,但我无法弄清楚我需要做什么才能让它在开始时创建我的最小对象?通过阅读文档我在我的应用程序配置中应该是我需要开始,但测试表明,池是零而不是我设置的最小值是4.CommonsPoolTargetSource不会创建对象

这是我的应用程序配置:

@Configuration 
@PropertySource({"classpath:config.properties"}) 
@ComponentScan(basePackages = {"com.mf.bb"}) 
public class AppConfig { 
    @Bean 
    public MessageSource messageSource() { 
     ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); 
     messageSource.setBasenames("classpath:i18n/messages"); 
     messageSource.setUseCodeAsDefaultMessage(true); 
     messageSource.setDefaultEncoding("UTF-8"); 
     messageSource.setCacheSeconds(0); 
     return messageSource; 
    } 

    @Bean 
    public static PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() { 
     return new PropertySourcesPlaceholderConfigurer(); 
    } 

    @Bean 
    @Scope("prototype") 
    public BBIDSApp bbIDSApp() { 
     return new BBIDSApp(); 
    } 

    @Bean 
    public CommonsPoolTargetSource commonsPoolTargetSource() {  
     CommonsPoolTargetSource commonsPoolTargetSource = new CommonsPoolTargetSource(); 
     commonsPoolTargetSource.setMinIdle(4); 
     commonsPoolTargetSource.setMaxSize(50); 
     commonsPoolTargetSource.setTargetBeanName("bbIDSApp"); 
     commonsPoolTargetSource.setTargetClass(BBIDSApp.class); 
     System.err.println("I'm alive!!!"); 
     return commonsPoolTargetSource; 
    } 

    @Bean 
    public ProxyFactoryBean proxyFactoryBean() { 
     ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean(); 
     proxyFactoryBean.setTargetSource(commonsPoolTargetSource()); 
     return proxyFactoryBean; 
    } 

    @Bean 
    public MethodInvokingFactoryBean poolConfigAdvisor() { 
     MethodInvokingFactoryBean poolConfigAdvisor = new MethodInvokingFactoryBean(); 
     poolConfigAdvisor.setTargetObject(commonsPoolTargetSource()); 
     poolConfigAdvisor.setTargetMethod("getMaxIdle"); 
     return poolConfigAdvisor; 
    } 

} 

回答

2

这是按预期工作,或更好地说,它工作,但不是你所期望的。不是Spring的CommonsPoolTargetSource,也不是正常的Commons Pool的GenericObjectPool不通过简单地创建池对象来初始化池中的对象数。

在春季,CommonsPoolTargetSource通过调用new GenericObjectPool(this)创建池。使用普通的简单GenericObjectPoolGenericObjectPool pool = new GenericObjectPool(new MyBeanFactory());也可以做到这一点,并且在构造函数中没有初始化逻辑,因此创建池实例时不会默认创建对象。

随着老式的香草共享池GenericObjectPool可以初始化minIdle对象是这样的:

  • 手动

    GenericObjectPool<MyBean> pool = new GenericObjectPool<MyBean>(new MyBeanFactory()); 
    pool.setMinIdle(4); 
    
    for (int i = 0; i < 4; i++) { 
        pool.addObject(); 
    } 
    
  • 有所自动的,但丑:

    GenericObjectPool<MyBean> pool = new GenericObjectPool<MyBean>(new MyBeanFactory()); 
    pool.setMinIdle(4); 
    
    pool.setTimeBetweenEvictionRunsMillis(1000); 
    Thread.currentThread().sleep(2000); 
    

对于Spring的CommonsPoolTargetSource,您无权访问池实例或addObject()方法。因此,您可以使用sleep()方法(很丑)与timeBetweenEvictionRunsMillis一起使用,或让普通实现在需要时自动调整池的大小(在需要时创建对象并将其添加到池中)。

会有另一种,第三种方法定制CommonsPoolTargetSource的,应该包括init方法:

public class CustomCommonsPoolTargetSource extends CommonsPoolTargetSource { 
    public void initializeMinIdleObjects() throws Exception { 
     List<BBIDSApp> apps = new ArrayList<BBIDSApp>(); 

     for(int i = 0; i < getMinIdle(); i++) { 
      apps.add((BBIDSApp) this.getTarget()); 
     } 

     for(BBIDSApp app : apps) { 
      this.releaseTarget(app); 
     } 

     apps.clear(); 
    } 
} 

,然后在你的AppConfig:

@Bean(initMethod="initializeMinIdleObjects") 
public CommonsPoolTargetSource commonsPoolTargetSource() {  
    CommonsPoolTargetSource commonsPoolTargetSource = new CustomCommonsPoolTargetSource(); 
    commonsPoolTargetSource.setMinIdle(4); 
    commonsPoolTargetSource.setMaxSize(50); 
    commonsPoolTargetSource.setTargetBeanName("bbIDSApp"); 
    commonsPoolTargetSource.setTargetClass(BBIDSApp.class); 
    System.err.println("I'm alive!!!"); 
    return commonsPoolTargetSource; 
}