Java Spring引导自动配置-bean创建顺序

Java Spring引导自动配置-bean创建顺序,java,spring,spring-boot,Java,Spring,Spring Boot,我有一个使用JPA的软件和应用程序 出于超出这个问题的原因,我在单独的静态配置类中提供了自定义JPAVendorAdapter。并且配置表现为非确定性 在我的Windows deksktop上,当我启用--debug时,我看到了预期的结果: JpaBaseConfiguration#JPAVENDOR适配器 -@ConditionalOnMissingBean(类型:org.springframework.orm.jpa.JpaVendorAdapter;搜索策略:全部) 找到以下[custom

我有一个使用JPA的软件和应用程序

出于超出这个问题的原因,我在单独的静态配置类中提供了自定义
JPAVendorAdapter
。并且配置表现为非确定性

在我的Windows deksktop上,当我启用
--debug
时,我看到了预期的结果:

JpaBaseConfiguration#JPAVENDOR适配器 -@ConditionalOnMissingBean(类型:org.springframework.orm.jpa.JpaVendorAdapter;搜索策略:全部) 找到以下[customJPAVendorAdapter](OnBeanCondition)

但一旦我将应用程序部署到某个服务器上,我就会得到:

JpaBaseConfiguration#JPAVENDOR适配器 -@ConditionalOnMissingBean(类型:org.springframework.orm.jpa.JpaVendorAdapter;搜索策略:全部) 未找到任何bean(在Bean条件下)

代码完全相同

请告诉我,在
JpaBaseConfiguration
启动并自动配置默认适配器之前,必须创建带有
JPAVendorAdapter
@Bean

编辑:

@ComponentScan(
        value = {"module.package"}
)
@EnableAutoConfiguration(exclude = {
        SecurityAutoConfiguration.
        DataSourceAutoConfiguration.class,
        HibernateJpaAutoConfiguration.class,
        JpaBaseConfiguration.class
    })
@EnableScheduling
@EnableConfigurationProperties
@Configuration
@Slf4j
public class MainConfig extends SpringBootServletInitializer implements SchedulingConfigurer {
 ...
}
@Configuration
@Slf4j
@Conditional(value = SelfHelpConfig.ModuleCondition.class)
@ComponentScan(basePackageClasses = SelfHelpModuleComponentScanPlaceholder.class)
public class SelfHelpConfig {

    public static class ModuleCondition extends AbstractModuleEnabledCondition {

        @Override
        public String getModuleId() {
            return "self-help";
        }
    }

    @Configuration
    @Conditional(value = SelfHelpConfig.ModuleCondition.class)
    static class JpaVendorConfig {

        @Bean
        public AbstractJpaVendorAdapter customJPAVendorAdapter(SpringHibernateJpaPersistenceProviderWithNamingStrategy jpaPersistenceProvider) {
            log.info("Creating custom JPA vendor adapter");

            return new HibernateJpaVendorAdapter() {
                @Override
                public PersistenceProvider getPersistenceProvider() {
                    return jpaPersistenceProvider;
                }
            };
        }
    }
}
配置非常分散,但希望我将介绍主要部分:

主配置:

@ComponentScan(
        value = {"module.package"}
)
@EnableAutoConfiguration(exclude = {
        SecurityAutoConfiguration.
        DataSourceAutoConfiguration.class,
        HibernateJpaAutoConfiguration.class,
        JpaBaseConfiguration.class
    })
@EnableScheduling
@EnableConfigurationProperties
@Configuration
@Slf4j
public class MainConfig extends SpringBootServletInitializer implements SchedulingConfigurer {
 ...
}
@Configuration
@Slf4j
@Conditional(value = SelfHelpConfig.ModuleCondition.class)
@ComponentScan(basePackageClasses = SelfHelpModuleComponentScanPlaceholder.class)
public class SelfHelpConfig {

    public static class ModuleCondition extends AbstractModuleEnabledCondition {

        @Override
        public String getModuleId() {
            return "self-help";
        }
    }

    @Configuration
    @Conditional(value = SelfHelpConfig.ModuleCondition.class)
    static class JpaVendorConfig {

        @Bean
        public AbstractJpaVendorAdapter customJPAVendorAdapter(SpringHibernateJpaPersistenceProviderWithNamingStrategy jpaPersistenceProvider) {
            log.info("Creating custom JPA vendor adapter");

            return new HibernateJpaVendorAdapter() {
                @Override
                public PersistenceProvider getPersistenceProvider() {
                    return jpaPersistenceProvider;
                }
            };
        }
    }
}
使用JPA的模块:

@ComponentScan(
        value = {"module.package"}
)
@EnableAutoConfiguration(exclude = {
        SecurityAutoConfiguration.
        DataSourceAutoConfiguration.class,
        HibernateJpaAutoConfiguration.class,
        JpaBaseConfiguration.class
    })
@EnableScheduling
@EnableConfigurationProperties
@Configuration
@Slf4j
public class MainConfig extends SpringBootServletInitializer implements SchedulingConfigurer {
 ...
}
@Configuration
@Slf4j
@Conditional(value = SelfHelpConfig.ModuleCondition.class)
@ComponentScan(basePackageClasses = SelfHelpModuleComponentScanPlaceholder.class)
public class SelfHelpConfig {

    public static class ModuleCondition extends AbstractModuleEnabledCondition {

        @Override
        public String getModuleId() {
            return "self-help";
        }
    }

    @Configuration
    @Conditional(value = SelfHelpConfig.ModuleCondition.class)
    static class JpaVendorConfig {

        @Bean
        public AbstractJpaVendorAdapter customJPAVendorAdapter(SpringHibernateJpaPersistenceProviderWithNamingStrategy jpaPersistenceProvider) {
            log.info("Creating custom JPA vendor adapter");

            return new HibernateJpaVendorAdapter() {
                @Override
                public PersistenceProvider getPersistenceProvider() {
                    return jpaPersistenceProvider;
                }
            };
        }
    }
}
此模块
@ComponentScan
发现数据库配置:

@Configuration
@EntityScan(basePackageClasses = SelfHelpModuleComponentScanPlaceholder.class)
@EnableJpaRepositories(basePackageClasses = SelfHelpModuleComponentScanPlaceholder.class)
@Import({DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
public class DBConfig {

}

如果JPAVendorConfig没有放在单独的类中,则根本不会应用它。如果在单独的类中,那么它在我的桌面上工作,但在部署到Linux服务器时不工作。

发布您的配置…首先,为什么您有两次这种情况,为什么在配置中嵌套配置,将其作为bean添加到out配置中也应该工作。但是你真的需要这个吗?这个适配器有什么特别之处,你需要一个定制的适配器吗?在我看来,你可以通过设置适当的属性来获得相同的结果,这会使事情变得更复杂。正如所解释的,如果不嵌套,它根本不起作用。曾经嵌套的工作“有时”。我需要为每个环境的表添加自定义前缀。例如,实现类似于
@Table(name=“${prefix}\u myTable”)
的功能,那么为什么不简单地注册一个自定义
命名策略
,它可以通过
应用程序.属性
简单地配置?而不是试图用条件句。您仍然不需要对条件进行双重检查(仅对嵌套的条件进行检查就足够了),但是只有一个在bean方法上具有条件的配置类也可以工作。命名策略采用的是类而不是bean,因此您无法向其中注入属性。