CommonsPoolTargetSource不会创建对象

时间:2014-06-26 18:42:02

标签: spring spring-aop spring-annotations

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

这是我的App配置:

@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;
    }

}

1 个答案:

答案 0 :(得分:2)

这是按预期工作的,或者更好地表示它正在工作,但并不像您期望的那样。不是Spring的CommonsPoolTargetSource,也不是普通的Commons Pool GenericObjectPool,只需创建池对象即可初始化池中的对象数。

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

使用普通的旧香草Commons Pool 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;
}