簡體   English   中英

使用泛型通過上下文獲取 spring bean

[英]Get spring bean via context using generic

我有一堆實現類型Repository<T ? extends Node>的存儲庫 bean Repository<T ? extends Node> Repository<T ? extends Node> 現在我可以從用戶那里獲取隨機節點列表,並且我想為每個節點獲取適當的存儲庫。 Spring 4.0RC1 開始,我們可以像這樣自動裝配存儲庫:

@Autowired Repository<SomeNode> someNodeRepository;

如此處所述

這很好用,但我的問題是如何根據泛型類型動態地做到這一點。

我想做的是:

public <T extends Node> T saveNode(T node) {
    Repository<T> repository = ctx.getBean(Repository.class, node.getClass());
    return repository.save(node);
}

其中第二個參數是泛型類型。 這當然不起作用,盡管它可以編譯。

我找不到任何/有關此的文檔。

你可以這樣做:

String[] beanNamesForType = ctx.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, node.getClass()));

// If you expect several beans of the same generic type then extract them as you wish. Otherwise, just take the first
Repository<T> repository = (Repository<T>) ctx.getBean(beanNamesForType[0]);

如果你能確保對每一個具體子Node (說SomeNode ),該類型的每個對象SomeNode將是一個實際的SomeNode ,而不是一個子類,或者代理服務器,它會很容易。 只需使用存儲庫名稱的約定(比如說SomeNodeRepository ),這將是微不足道的:

Repository<T> repository = ctx.getBean(node.getClass().getSimpleName()
        + "Repository", Repository.class);

但是你知道獲得子類或代理的風險很高......

因此,您可以嘗試讓每個Node子類實現nameForRepo方法:

class Node {
    ...
    abstract String getNameForRepo();
}

然后在子類中

class SomeNode {
    static private final nameForRepo = "SomeNode";
    ...
    String getNameForRepo() {
        return nameForRepo;
    }
}

這樣,即使您獲得代理或子類,您也可以:

public <T extends Node> T saveNode(T node) {
    Repository<T> repository = ctx.getBean(node.getNameForRepository()
            + "Repository", Repository.class);
    return repository.save(node);
}

或者,該方法可以直接返回存儲庫名稱。

如果我理解得很好,你想獲得具有Repository類和不同泛型類型的bean實例嗎?

我是afraide你沒有春天的動態方式,但我有一個解決方案:

  1. 您的泛型類型應該是類中的一個字段,您必須在Repository類中有一個構造函數來設置泛型類型,您的Repository類應該是這樣的:

    public class Repository<T>{ Class<T> nodeClass; public Repository(Class<?> clazz){ this.nodeClass = clazz; } // your codes... }

  2. 為每個Node聲明一個Repository bean,假設您有Repository和Repository,如果您使用的是xml配置,則需要添加:

    <bean id="someNodeRep" class="your.package.Repository"> <constructor-arg> <value>your.package.SomeNode</value> </constructor-arg> </bean> <bean id="otherNodeRep" class="your.package.Repository"> <constructor-arg> <value>your.package.OtherNode</value> </constructor-arg> </bean>

  3. 以這種方式“自動裝配”您的存儲庫:

    @Autowired @Qualifier("someNodeRep") Repository<SomeNode> someNodeRepository;

    @Autowired @Qualifier("otherNodeRep") Repository<OtherNode> otherNodeRepository;

從 Spring 5.1 開始,您可以像這樣獲得Repository<T>類型的 bean:

public static <T> Repository<T> getRepositoryFor(Class<T> clazz)
{
    ResolvableType type = ResolvableType.forClassWithGenerics(Repository.class, clazz);
    return (Repository<T>) context.getBeanProvider(type).getObject();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM