【问题标题】:Spring Boot How to load only specified @Repository componentsSpring Boot 如何仅加载指定的@Repository 组件
【发布时间】:2020-02-13 16:59:45
【问题描述】:

我有一个项目,其中包含许多由 @Repository 注释的 Dao。

还有几个 spring boot 项目,每个项目都有自己的 spring 上下文,可以独立运行,并且它们具有对包含 Daos 的项目的引用。

问题是,我不想在每个项目中将所有 Dao 加载到 spring 上下文中。每个 spring boot 项目只需要一些指定的 Dao。

我过去常常通过在每个项目的 XML 配置中将 Dao 类定义为 bean 来指定它们。

现在我们正在转向基于 java 和注解的配置。

有没有办法告诉spring上下文只加载我指定的@Repository?

我知道我可以创建一个@Configuration 类并定义@Bean 方法,但我仍然需要将它们视为@Repository 而不是普通的bean。知道这是否受支持以及如何实施?

【问题讨论】:

    标签: spring spring-boot


    【解决方案1】:

    您可以在每个 DAO 类上使用@Conditional。 仅当满足使用 @Conditional 注释提到的条件时,才会在上下文中加载类。你可以有这样的条件:

    @ConditionalOnProperty(
        value="module.name", 
        havingValue = "module1", 
        matchIfMissing = false)
    class DaoForModule1 {
    

    当且仅当属性module.name 的值为module1 时,这将加载DaoModule1。如果你想在没有设置proerty的情况下加载这个DaoModule1,你可以把matchIfMissing改成true

    也可以使用@Profile注解来限制根据profile加载的类

    @Profile("module2")
    class DaoForModule2 {
    

    仅当您在活动配置文件列表中有module2 时,才会加载DaoForModule2。但我不喜欢配置文件,因为配置文件的用例不同。我们通常使用配置文件来指定基于环境的可变资源。

    【讨论】:

      【解决方案2】:

      根据您的问题,我假设您想在其他几个 Spring 项目中重用具有多个存储库和 JPA 实体对象的 Spring DAO 项目,这些对象可能属于不同的数据源。您更喜欢仅加载一组特定的 JPA 实体/存储库。第一步是将相关实体和存储库组织到不同的包中,并将该项目包含在其他项目的路径中。

      这是处理此问题的一种方法,假设您已将存储库和实体分成不同的包。创建您自己的 Configuration bean,该 bean 将使用所需的特定包和数据源实例化 JPA EntityManagerFactory bean。在下面的代码中,下面的 EntityManagerFactory 将从MODEL_PACKAGE 加载实体,从REPOSITORIES_PACKAGE 加载存储库。

      @Configuration
      @ComponentScan(basePackages = MODEL_PACKAGE)
      @EnableJpaRepositories(basePackages = REPOSITORIES_PACKAGE,
              entityManagerFactoryRef = "ENTITY_MANAGER_FACTORY")
      @EnableTransactionManagement
      public class PersistenceConfig {
      
          public static final String MODEL_PACKAGE = "Your model package";
          public static final String REPOSITORIES_PACKAGE = "Your repository package";
      
              public static final String ENTITY_MANAGER_FACTORY = "entity_manager_factory";
          public static final String TRANSACTION_MANAGER = "transaction_manager";
      
          @Autowired //This is to get your property file entries (DB connection, etc).
          private Environment environment;
      
          @Bean(DATA_SOURCE)
          public DataSource dataSource() {
              //Create your datasource from environment properties.  Example - org.apache.tomcat.jdbc.pool.DataSource
          }
      
          @Bean(ENTITY_MANAGER_FACTORY) @Autowired
          public LocalContainerEntityManagerFactoryBean entityManagerFactory(
                  @Qualifier(DATA_SOURCE) DataSource dataSource) throws IllegalStateException  {
              LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
              entityManagerFactoryBean.setDataSource(dataSource);
              Properties jpaProperties = new Properties();
              // set properties for your JPA, for example, hibernate.dialect, hibernate.format_sql, etc.
      
              entityManagerFactoryBean.setJpaProperties(jpaProperties);
              entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
              entityManagerFactoryBean.setPackagesToScan(MODEL_PACKAGE);
          }
      
          @Bean(TRANSACTION_MANAGER) @Autowired
          @Primary
          @Qualifier(value = "transactionManager")
          public JpaTransactionManager transactionManager(
                  @Qualifier(ENTITY_MANAGER_FACTORY) EntityManagerFactory entityManagerFactory) {
              JpaTransactionManager transactionManager = new JpaTransactionManager();    
              transactionManager.setEntityManagerFactory(entityManagerFactory);    
              return transactionManager;
      

      【讨论】:

        【解决方案3】:

        @SpringBootApplication 只需组合 @EnableAutoConfiguration@SpringBootConfiguration@ComponentScan

        @ComponentScan 是导致扫描包下的所有 @Repository bean 自动注册的人,这是您不希望发生的事情。

        因此您可以单独使用这些注释,但不包括@ComponentScan。并使用@Import 显式定义要注册的bean。

        主应用程序类如下所示:

        @SpringBootConfiguration
        @EnableAutoConfiguration
        @Import(value = {FooRepoistory.class, BarRepository.class,.......})
        public class Application {
        
            public static void main(String[] args) {
                    SpringApplication.run(Application.class, args);
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-12-31
          • 2018-04-10
          • 2020-02-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-30
          相关资源
          最近更新 更多