我们目前有一个应用程序,它使用具有相同模式的多个数据库。目前,我们正在使用自定义解决方案,根据用户的会话进行切换。这通过
工作public final class DataSourceProxy extends BasicDataSource {
...
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null && auth.getDetails() instanceof Map) {
Map<String, String> details = (Map<String, String>) auth.getDetails();
String targetUrl = details.get("database");
Connection c = super.getConnection();
Statement s = c.createStatement();
s.execute("USE " + targetUrl + ";");
s.close();
return c;
} else {
return super.getConnection();
}
}
现在我们要使用AbstractRoutingDataSource
构建解决方案。问题是:
@Component
public class CustomRoutingDataSource extends AbstractRoutingDataSource {
@Autowired
Environment env;
@Autowired
DbDetailsRepositoy repo;
public CustomRoutingDataSource() {
Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
for(DBDetails dbd : repo.findAll() {
// create DataSource and put it into the map
}
setTargetDataSources(new HashMap<Object, Object>());
}
@Override
protected Object determineCurrentLookupKey() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null && auth.getDetails() instanceof Map) {
Map<String, String> details = (Map<String, String>) auth.getDetails();
return details.get("database");
}
return null;
}
}
在构造函数内部(甚至通过@PostConstruct
),我们必须填充targetDataSources Map
。但是(!)为此我们需要存储在另一个数据库中的连接细节,该数据库有自己的数据源和实体管理器。
看起来Spring无法确定Bean构造的顺序,或者我可能只是遗漏了一些东西。它在访问存储库时总是给出NullPointerException
(btw是JpaRepository
)。
我们正在使用Spring 3.2.3,Spring Data,Hibernate 4.2。 Spring和Spring Security的完整注释和Java代码配置。
请帮助我们!
答案 0 :(得分:1)
Spring当然必须在之前调用构造函数才能填充属性。但这不是Spring的东西,这是基本的Java 101,也是使用现场注入的众多缺点之一。
要避免这种情况,只需将依赖项添加到构造函数中:
@Component
class CustomRoutingDataSource extends AbstractRoutingDataSource {
@Autowired
public CustomRoutingDataSource(DbDetailsRepository repo, Environment environment) {
…
}
…
}