如何在众多 JAR 之间分离我的 Spring JPA 配置?

Posted

技术标签:

【中文标题】如何在众多 JAR 之间分离我的 Spring JPA 配置?【英文标题】:How to separate my Spring JPA configuration between numerous JARs? 【发布时间】:2017-11-30 01:12:01 【问题描述】:

我有一个用例,我需要将我的 Spring 配置分成 2 个完全独立的应用程序。

应用程序 #1 将包含带有 Hibernate 映射、JPA 存储库、DTO 模型以及从 DAO 转换为 DTO 的逻辑的 DAO 模型。

应用程序 #2 将包含 RESTful 控制器和包含所有业务逻辑的服务类。


应用#1​​strong>配置:

// For application startup
package com.appone.pkg.one

@SpringBootApplication
public class Application 
    public static void main(String[] args) 
        SpringApplication.run(Application.class, args);
    


// For global configuration files across numerous projects
package com.appone.pkg.two

@Configuration
public class GlobalAppConfig 

    @Bean
    MapperFacade mapperFacade() 
        MapperFactory factory = new DefaultMapperFactory.Builder().build();

        factory.classMap(Group.class, GroupDTO.class).byDefault().register();
        factory.classMap(Role.class, RoleDTO.class).byDefault().register();
        factory.classMap(User.class, UserDTO.class).byDefault().register();

        return factory.getMapperFacade();
    
 

// For configuration aspects important for 1 project in particular
package com.appone.pkg.three

@Configuration
@EnableJpaRepositories("com.pkg.three.jpa.repository")
public class AppTwoConfig 

    @Autowired
    private EntityManager em;
    private RepositoryFactorySupport factorySupport;

    private void initialize()
        if(factorySupport == null)
            factorySupport = new JpaRepositoryFactory(em);
        
    

    @Bean
    GroupRepository groupRepository()
        initialize();
        return factorySupport.getRepository(GroupRepository.class);
    
    @Bean
    RoleRepository roleRepository()
        initialize();
        return factorySupport.getRepository(RoleRepository.class);
    
    @Bean
    UserRepository userRepository()
        initialize();
        return factorySupport.getRepository(UserRepository.class);
    
    @Bean
    GroupValidator groupValidator()
        return new GroupValidator();
    
    @Bean
    UserValidator userValidator()
        return new UserValidator();
    
    @Bean
    ResourceMapper resourceMapper()
        return new ResourceMapper();
    

应用#2配置:

package com.apptwo.pkg.one;

@SpringBootApplication
@EnableAutoConfiguration
@EntityScan(basePackageClasses = com.appone.pkg.three.AppTwoConfig.class)
public class ApplicationTwo 
    public static void main(String[] args) 
        SpringApplication.run(ApplicationTwo.class, args);
    

应用 #2 数据加载:

package com.apptwo.pkg.two;

@Component
public class DataLoader implements ApplicationRunner 

    @Autowired
    private GroupRepository groupRepository;
    @Autowired
    private RoleRepository roleRepository;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private ResourceMapper resourceMapper;

    /**
     * Loads initial data into the h2 database.
     */
    public void run(ApplicationArguments args) 
        // Load the initial data ... 
    

这是我尝试启动应用程序 #2 时遇到的异常。应用程序 #1 可以自行启动,但我没有使用那里的存储库,并且相信如果我尝试它可能会引发错误。最终我只想要应用程序#2中的逻辑。你对我做错了什么有什么想法吗?

我需要初始化应用程序#1 配置中的所有依赖项,然后在运行应用程序#2 配置之前从应用程序#2 中运行该配置。

说明: com.apptwo.pkg.two.DataLoader 中的字段 groupRepository 需要一个 bean 类型 'com.appone.pkg.three.jpa.repository.GroupRepository' 找不到。

动作: 考虑在 'com.appone.pkg.three.jpa.repository.GroupRepository' 你的配置。

【问题讨论】:

您不应该在另一个 Spring Boot 应用程序中包含一个 Spring Boot 应用程序。我怀疑 app1 需要是一个弹簧启动应用程序,而不是可能应该是一个常规的 jar 文件。 如果不是 Spring Boot,我还能使用 Spring JPA Repositories、Autowired 和所有其他有趣的东西吗? 为什么不呢。 app1 不是一个应用程序,只是一个带有依赖项的 jar。 哦,我想我把它弄得太复杂了,让一切都成为 Spring Boot。当我有机会时,我会尝试将 AppOne 转换为标准的 Maven 应用程序,看看是否能解决它。 感谢您的快速回复。 【参考方案1】:

感谢大家的共同努力,我找到了解决方案。

部分帮助来自这篇文章:Can't Autowire @Repository annotated interface in Spring Boot

第 1 步:

从 Application #1 中删除了 Application.class,使其不能作为独立的 Spring Boot 应用程序运行。

第 2 步:

我像这样更改了 AppTwoConfig.java,

// For configuration aspects important for 1 project in particular
package com.appone.pkg.three

@Configuration
@EnableJpaRepositories("com.pkg.three.jpa.repository")
@EntityScan("com.pkg.three.jpa.model")
public class AppTwoConfig 

    @Bean
    GroupValidator groupValidator()
        return new GroupValidator();
    
    @Bean
    UserValidator userValidator()
        return new UserValidator();
    
    @Bean
    ResourceMapper resourceMapper()
       return new ResourceMapper();
    

第三步:

我更改了应作为 Spring Boot 应用程序运行的 Application #2 内的 Application.java。

package com.apptwo.pkg.one;

@SpringBootApplication
@EnableAutoConfiguration
@ComponentScan(basePackageClasses = 
        com.apptwo.pkg.one.config.AppConfig.class,
        com.appone.pkg.two.GlobalAppConfig.class,
        com.appone.pkg.three.AppTwoConfig.class
)
public class Application 
    public static void main(String[] args) 
        SpringApplication.run(Application.class, args);
    

【讨论】:

【参考方案2】:

组件 Scan only 扫描com.apptwo.pkg.one 的子包。你必须在@SpringBootApplication中配置正确的包

@SpringBootApplication(basePackages ="com.appone", "com.apptwo")

【讨论】:

以上是关于如何在众多 JAR 之间分离我的 Spring JPA 配置?的主要内容,如果未能解决你的问题,请参考以下文章

spring boot 打jar包分离lib和resources

如何使用 spring-data-neo4j-cross-store 在 neo4j 和 postgres 之间的部分 NodeEntity 上支持跨存储持久性?

Spring Boot 打包分离依赖 JAR 和配置文件

spring boot+vue前后端项目的分离(我的第一个前后端分离项目)

五:JAVA日志体系

spring/boot 打包,资源/配置/业务文件分离