我一直在用一个Web应用程序的常见用例来撕掉我的头发。我有一个Spring-Boot应用程序,它使用REST存储库,JPA等。问题是我有两个数据源:
由于第二个数据源特定于经过身份验证的用户,因此我尝试使用AbstractRoutingDataSource根据Principal用户在身份验证后路由到正确的数据源。
让我疯狂的是,Spring-Boot正在激励我在启动时实例化这个数据源。我已经尝试了我能想到的一切,包括Lazy和Scope注释。如果我使用会话范围,则应用程序会抛出有关启动时不存在会话的错误。 @Lazy似乎没有任何帮助。无论我使用什么注释,数据库都是在Spring Boot启动时实例化的,并且没有找到任何基本上崩溃整个应用程序的查找键。
另一个问题是Rest Repository API使IMO成为指定要使用的实际数据源的可怕方法。如果你有多个使用Spring Boot的数据源,你必须处理Qualifier注释,这是一个运行时调试的噩梦。
非常感谢任何建议。
答案 0 :(得分:1)
您的问题在于身份验证管理器配置。所有样本和指南都会在GlobalAuthenticationConfigurerAdapter
中设置,例如它看起来像是SimpleEmbeddedSecurityConfiguration
的内部类:
@Configuration
public static class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter
{
@Bean(name = Global.AUTHENTICATION_DATA_QUALIFIER + "DataSource")
public DataSource dataSource()
{
return new EmbeddedDatabaseBuilder().setName("authdb").setType(EmbeddedDatabaseType.H2).addScripts("security/schema.sql", "security/data.sql").build();
}
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception
{
auth.jdbcAuthentication().dataSource(dataSource()).passwordEncoder(passwordEncoder());
}
}
如果您不使用GlobalAuthenticationConfigurerAdapter
,则在创建安全过滤器期间(DataSource
@Primary
之前,Spring {0}会获取DataSource
bean甚至已被注册)并且整个JPA初始化开始超级早期(坏主意)。
更新:身份验证管理器不是唯一的问题。如果你需要一个会话作用域@Primary
DataSource
(我说不太常见),你需要在启动时关闭所有想要访问数据库的东西(Hibernate和Spring Boot in各个地方)。例如:
spring.datasource.initialize: false
spring.jpa.hibernate.ddlAuto: none
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults: false
spring.jpa.properties.hibernate.dialect: H2
进一步更新:如果您正在使用Actuator,它还希望在启动时使用主数据源作为运行状况指示器。你可以通过私有相同类型的bean来覆盖它,例如
@Bean
@Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
@Lazy
public DataSourcePublicMetrics dataSourcePublicMetrics() {
return new DataSourcePublicMetrics();
}
P.S。我相信在Spring Boot 1.2.2中可能不需要GlobalAuthenticationConfigurerAdapter
,但它在1.2.1或1.1.10中。