簡體   English   中英

如何將Spring上下文作為方法參數傳遞?

[英]How to pass Spring context as a method argument?

我需要有關Spring的幫助(SpringBoot 1.3.2.RELEASE,Spring 4.3.11.RELEASE)。 用例很特殊,需要解釋。

我有一個Spring應用程序來管理客戶發送的請求。 為了處理這些請求,我們需要使用帶有@Autowired批注聲明的服務。 很經典。

最近,我們決定處理來自其他國家的新型請求。 關鍵是面對不同情況和不同類型的請求,我們決定實施策略模式。 ->根據請求的類型,我們執行在運行時選擇的策略。 每個策略都包含在一個具體的類中,並且所有策略共享相同的接口。

所以,我有:

  • 完全完成請求處理的主類。 為了完成其工作,此類用於調用使用@Autowired批注聲明的somes服務。

我現在有 :

  • 一個僅初始化請求處理的主類。 為了完成其工作,此類將在運行時根據某些條件實例化一個策略。
  • 一個帶有2個方法的IStrategy(接口),這將由我的2個具體類實現
  • 2個具體的班級(還有更多的班級)將完成這項工作。 非常重要的一點是,這些具體的類將在加載Spring上下文之后在運行時實例化。

問題在於,在加載Spring上下文之后,將無法再使用@Autowired注釋。 我想在我的具體策略類中使用的所有服務都無法再由@Autowired調用,並保持為NULL。

通過將需要的服務作為參數傳遞給具體的策略類,我找到了一種解決方法,但是作為一種參數,我必須傳遞的服務數量因一種策略而異。

我想我應該通過整個Spring上下文,但是我不知道該怎么做。 而且我也不知道如何從上下文訪問所有帶注釋的服務。

PS:我不顯示代碼行,因為我認為實際上沒有必要。 如果您認為代碼更明確,我會發送一些。

提前感謝。

您應該聲明一個工廠來映射依賴關系,而不是將服務聲明為bean,而是在將服務的具體實例返回到注入器之前,它將檢查請求。 在這里看看:

https://grokonez.com/spring-framework/spring-core/use-spring-factory-method-create-spring-bean

您可以使用下面的類來靜態獲取應用程序上下文和Bean

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

@Service
public class BeanUtil implements ApplicationContextAware {

    private static ApplicationContext context;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }
    public static <T> T getBean(Class<T> beanClass) {
        return context.getBean(beanClass);
    }



}

大家很快回答我。 首先,對於您最近對所有評論的回答如此,我必須道歉。 上一次沖刺是一個很大的負擔,而新的沖刺並不好^^

我的需要是在Spring上下文創建和加載應用程序的所有部分之后,在對象上創建對象。 作為策略模式的一部分,我必須在運行時實例化一個類,具體取決於必須處理的請求文件中的某些值。 此類需要使用@Autowired批注聲明的許多服務,但是所有自動裝配的對象仍為' null ',因為在加載上下文之后調用了該服務。

這是我首先要使用的代碼。 沒有春天就可以了。

Function<Document, IStrategy> func = doc -> {
        String strategyToApply = "";
        IStrategy strategy = null;
        switch(doc.getPlace()) {
            case "Paris":
                strategyToApply = "strategies_classes.ProcessParis";
                break;
            case "New York":
                strategyToApply = "strategies_classes.ProcessNewYork";
                break;
            }
            case "Roma":
                ...
        try {
            **Class<?> classToUse = Class.forName(strategyToApply);
            strategy = (IStrategy) classToUse.newInstance();**
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return strategy;
};

Consumer<Document> consumerStrategy = doc -> {
    IStrategy strategy = func.apply(doc);
    strategy.bookRequest(doc);
};
documents.stream()
    .forEach(consumerStrategy);

我終於找到了魔法對象。 當Spring對象的生命周期不符合我們自己的概念時,這是一個很好的解決方法。

要使用它,您只需使用@Autowired進行聲明:

@Autowired
private AutowireCapableBeanFactory autowireBeanFactory;

注意,AutowireCapableBeanFactory是一個Spring對象,您無需在其他任何地方聲明!

然后,要使用它,很簡單(我設計了一種全新的服務,與您在上面看到的完全不同,但是它的作用相同):

public <T> T getStrategyToUse(Entity bookingCtr, Funder funder, StrategyEnum strategy) throws FunctionalException {
        String strategyToApply = null;
        strategyToApply = strategyDao.getClassToApply(bookingCtr, funder, strategy);
        Class<?> classToUse;
        try {
            classToUse = Class.forName(strategyToApply);
            T strat = (T) **autowireBeanFactory.getBean**(classToUse);
            return (T) strat;
        } catch (ClassNotFoundException e) {
            LOGGER.error("The indicated Strategy class was not found", e);
        }
        return null;
    }

在運行時加載時,將立即實例化所選的類,並且其所有自動裝配對象將不再為null。

我希望這將有所幫助。

暫無
暫無

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

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