Spring boot Spring数据JPA配置的模块化

Spring boot Spring数据JPA配置的模块化,spring-boot,spring-data-jpa,spring-data,Spring Boot,Spring Data Jpa,Spring Data,我们正在寻找不同模块分别指定@ComponentScan、@EnableJpaRepositories和EntityManagerFactory.setPackagesToScan的方法 我们将多个代码模块组合到web应用程序中。此外,我们允许对基础代码进行特定于客户的扩展,从而可以添加额外的包。在我的测试中,我发现我可以添加一个额外的java配置类,@ComponentScan和@EnableJpaRepositories中的额外包也被选中。我在想,如果我能使用@EntityScan,我会看到

我们正在寻找不同模块分别指定@ComponentScan、@EnableJpaRepositories和EntityManagerFactory.setPackagesToScan的方法

我们将多个代码模块组合到web应用程序中。此外,我们允许对基础代码进行特定于客户的扩展,从而可以添加额外的包。在我的测试中,我发现我可以添加一个额外的java配置类,@ComponentScan和@EnableJpaRepositories中的额外包也被选中。我在想,如果我能使用@EntityScan,我会看到类似的行为

但是,我们正在EntityManagerFactory中执行一些定制,因此@EntityScan不再是一个选项。我认为我们不想为每个模块指定另一个EntityManagerFactory。方法setPacakgesToScan执行包的替换(而不是添加到当前列表)

已经有很多关于设置PackageScon的能力的帖子,但这似乎大大增加了复杂性

基本配置类示例

@Configuration
@EnableJpaRepositories(basePackages = { 
        "a", "b", "c"
 }
,repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class
)
@ComponentScan(basePackages = {
        "a", "b", "c"
}
)
public class BaseConfig {       
    @Bean
    public EntityManagerFactory entityManagerFactory() throws NamingException {
        LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
        emf.setJtaDataSource(dataSource());
        emf.setPackagesToScan(new String[] {"a", "b", "c"})
    }
}
@Configuration
@EnableJpaRepositories(basePackages = { 
        "d"
 }
,repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class
)
@ComponentScan(basePackages = {
        "d"
}
)
public class ExtensionConfig {      
    @Bean
    public EntityManagerFactory entityManagerFactory() throws NamingException {
        LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
        emf.setJtaDataSource(dataSource());
        emf.setPackagesToScan(new String[] {"d"})
    }
}
扩展配置类示例

@Configuration
@EnableJpaRepositories(basePackages = { 
        "a", "b", "c"
 }
,repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class
)
@ComponentScan(basePackages = {
        "a", "b", "c"
}
)
public class BaseConfig {       
    @Bean
    public EntityManagerFactory entityManagerFactory() throws NamingException {
        LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
        emf.setJtaDataSource(dataSource());
        emf.setPackagesToScan(new String[] {"a", "b", "c"})
    }
}
@Configuration
@EnableJpaRepositories(basePackages = { 
        "d"
 }
,repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class
)
@ComponentScan(basePackages = {
        "d"
}
)
public class ExtensionConfig {      
    @Bean
    public EntityManagerFactory entityManagerFactory() throws NamingException {
        LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
        emf.setJtaDataSource(dataSource());
        emf.setPackagesToScan(new String[] {"d"})
    }
}
有没有其他方法可以实现这种行为


谢谢。

您可以尝试以下方法,尽管我不确定这是最好的方法:

为包列表创建holder类。它必须可由客户端扩展模块访问:

公共类EmfPackages{
私有最终字符串[]包;
公共EmfPackages(字符串[]包){
这个。包=包;
}
公共字符串[]getPackages(){
退回此文件包;
}
}
然后调整两个配置类:

public类BaseConfig{
@豆子
公共EMFPackages baseEmfPackages(){
返回新的EmfPackages(新字符串[]{“a”、“b”、“c”});
}    
@豆子
//两个“持有者”现在都被注入到这里
//AFAIK此功能在Spring 4中起作用+
公共EntityManagerFactory EntityManagerFactory(列出emfPackages)引发NamingException{
//实际上,这是Java8+风格,如果需要,可以针对较低版本进行调整
最终字符串[]combinedPackages=emfPackages.stream()
.flatMap(p->Arrays.stream(p.getPackages()))
.collect(收集器.toList())
.toArray(新字符串[0]{});
LocalContainerEntityManagerFactoryBean emf=新的LocalContainerEntityManagerFactoryBean();
setJtaDataSource(dataSource());
emf.setPackagesToScan(组合包)
}    
}
公共类扩展配置{
@豆子
公共EmfPackages扩展EmfPackages(){
返回新的EmfPackages(新字符串[]{“d”});
}
}