1

我们目前有一个应用程序使用具有相同架构的多个数据库。目前,我们正在使用自定义解决方案根据用户的会话在它们之间进行切换。这通过

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访问存储库时它总是给出 a (顺便说一句是 a JpaRepository)。

我们正在使用 Spring 3.2.3、Spring Data、Hibernate 4.2。Spring 和 Spring Security 的完整注释和 Java-Code 配置。

请帮助我们!

4

1 回答 1

1

Spring 当然必须先调用构造函数才能填充属性。但这不是 Spring 的东西,这是基本的 Java 101,也是使用字段注入的众多缺点之一。

为避免这种情况,只需将您的依赖项添加到构造函数中:

@Component
class CustomRoutingDataSource extends AbstractRoutingDataSource {

  @Autowired
  public CustomRoutingDataSource(DbDetailsRepository repo, Environment environment) {
    …
  }
  …
}
于 2013-07-10T16:08:28.547 回答