Spring:如何多次重用相同的配置

时间:2016-03-30 01:51:01

标签: java spring

我有几套类似的豆子。例如,我可以连接数据库,监视该数据库,该数据库的DAO,该数据库的线程池等等。并且我想在相同的上下文中多次实例化这组bean,具有稍微不同的属性(例如,具有不同的主机名)。我想要这样的东西:


abstract class ContextTemplate {
    abstract String dbHost();

    @Bean
    DataSource dataSource() { return new DataSourceImpl(dbHost()); }

    @Bean
    DbMonitoring dbMonitoring() { return new DbMonitoring(dataSource()); }}

    // and ten more db-specific beans
}

@Configuration(prefix = "primary-")
class PrimaryDbContext extends ContextTemplate {
    @Override
    String dbHost() { return "primary.host"; }
}

@Configuration(prefix = "slow-reqs-")
class SlowRequestsContext extends ContextTemplate {
    @Override
    String dbHost() { return "slow.requests.host"; }
}

@Configuration
@Import({
    PrimaryContext.class,
    SlowRequestsContext.class,
})
class MyContext {
}

通过实例化这个虚构配置,我想要一个包含bean primary-dataSourceprimary-monitoringslow-reqs-dataSourceslow-reqs-monitoring的上下文。

关键是PrimaryDbContextSlowRequestsContext中的每一个都应该在一个结果应用程序上下文中发出几个非常相似的bean定义。

Spring可以这样吗?

修改:创建了feature request in the Spring tracker

2 个答案:

答案 0 :(得分:1)

我知道这个解决方案看起来不像你的例子。但是你不能用任何其他方式改变bean名称,只能手动改变。创建自定义工厂后处理器:

<form method ="post" onsubmit="return confirm("Are you sure you want to delete?")">
    <button name = "delete">Delete Image</button>
</form>

  <?php
 if(isset($_POST['delete']))
{
     $img_path=$_POST['ipath'];
     $imgid=$_POST['imgid'];
     $link = mysqli_connect($host, $username, $password, $db);
     $delete = "DELETE FROM images_info WHERE Image_Id = $imgid";
     $result3 = mysqli_query($link, $delete);
     echo "Image Deleted : $imgid";
     mysqli_close($link);
 }
   ?>

在配置中注册后处理器:

public class DbRegistryPostProcessor implements BeanFactoryPostProcessor{

    private String hostName;
    private String prefix;

    public BeanFactoryPostProcessor(Strin prefix, String hostName){
        this.prefix = prefix;
        this.hostName = hostName;
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {
        factory.registerSingleton(prefix+"dataSource", dataSource());
        factory.registerSingleton(prefix+"dbMonitoring", dbMonitoring());
    }


    DataSource dataSource() { return new DataSourceImpl(hostName); }

    DbMonitoring dbMonitoring() { return new DbMonitoring(dataSource()); }}

    // and ten more db-specific beans
}

当然,使用这种方法,您的bean将不会被其他后处理器处理(例如使用@Configuration public class MyContext { @Bean public DbRegistryPostProcessor primaryDbProcessor(){ return new DbRegistryPostProcessor("primary-", "primary.host"); } @Bean public DbRegistryPostProcessor secondaryDbProcessor(){ return new DbRegistryPostProcessor("secondary-", "secondary.host"); } } )。如果您需要其他后处理器处理bean,则可以实现自定义PropertySourcesPlaceholderConfigurer而不是BeanDefinitionRegistryPostProcessor

答案 1 :(得分:0)

动态地,您可以通过维护一个标志来切换不同的数据源,您可以通过点击在cookie或应用程序上下文范围内设置标志的Servlet来更改该标志。

只需注册一个ContextTemplate的bean,内部保留两个ContextTemplate

  • 实例化主要和次要ContextTemplate一次
  • 覆盖方法
  • 根据旗帜决定。

例如:

@Component
public class MyContextTemplate implements InitializingBean, ContextTemplate {

    private ContextTemplate primary;
    private ContextTemplate secondary;

    @Override
    public void afterPropertiesSet() {
        // initialize primary and secondary ContextTemplate  
        // you can initialize them in default constructor of this class also
    }

    public DataSource dataSource() {
       if(flat-set) {
          return primary.dataSource();
       }
       return secondary.dataSource();
    }

    public DbMonitoring dbMonitoring() {
       if(flat-set) {
          return primary.dbMonitoring();
       }
       return secondary.dbMonitoring();
    }
    // implement other methods
}

您也可以注册多个ContextTemplate bean,并将MyContextTemplate标记为primary bean,以解决自动布线冲突问题。

考虑一些符合您要求的设计模式:

状态模式的快照:

enter image description here