簡體   English   中英

如何在 Spring boot 控制台應用程序中將 spring bean 注入非托管 bean?

[英]How do I inject spring beans into non-managed beans in a Spring boot console application?

我嘗試遵循此處的建議: https : //www.baeldung.com/spring-inject-bean-into-unmanaged-objects

只是發現它正在編譯但實際上並沒有做它應該做的。 未在非托管對象中設置自動裝配的 bean。


@SpringBootApplication
@EnableSpringConfigured
public class SpringApp {

...


public class ApiClient {

    private static String result = "not set";

    //this would be called from another applicaiton written in a different language potentially.
    public String apiInterface(String message) {
        //This is where we're going to have to create Spring, where the languages 'join'.
        SpringApplicationBuilder builder = new SpringApplicationBuilder(SpringApp.class);
        builder.run();
        System.out.println("Running legacy code...");
        LegacyCode oldCode = new LegacyCode();
        result = oldCode.doLegacyStuff("hello world");
        
        return result;
    }

}


...

@Configurable(preConstruction = true)
public class LegacyCode {
    @Autowired
    MessageSender sender; //let's pretend we Spring-fied this bit of code but not the Legacy code that uses it.

    public String doLegacyStuff(String message) {        
        sender.send(message);
        sender.close();       
        
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
            return "interupted";
        }

        return "ok";
    }
}

這就是代碼的要點。 完整代碼在 github 上結束: https : //github.com/AlexMakesSoftware/SpringConsoleApp3

我得到的輸出是:

Exception in thread "main" java.lang.NullPointerException
        at demo.LegacyCode.doLegacyStuff(LegacyCode.java:13)
        at demo.ApiClient.apiInterface(ApiClient.java:17)
        at demo.DummyApplication.main(DummyApplication.java:7)

這只能意味着 @Autowired MessageSender 沒有被注入。

任何想法我做錯了什么?

編輯:我應該指出,這是一個更復雜的項目的簡單示例,用於將 Spring 慢慢集成到遺留代碼庫中。 我不能簡單地“全部使用 Spring”,也不能改變 Spring 初始化的位置,因為這個遺留代碼是從另一個用另一種語言編寫但在 JVM 中運行的應用程序(盡管是更簡單的應用程序)調用的。 是的,這很可怕,我知道。

問題是:

您正在使用new關鍵字初始化LegacyCode 現在的問題是LegacyCode使用autowire ,它僅適用於使用 Spring 創建的 bean。 因此,作為@autowired NPE @autowired用於new

解決方案 :

您可以使用@Component標記您的LegacyCode ,然后在ApiClient autowire它。 這樣MessageSender bean 將被創建並可用。

我希望這可以幫助您並消除您的疑慮。 如果沒有,請告訴我,我會幫助您解決。

祝你好運,快樂編碼!

@SpringBootApplication注解必須在你的主類中使用。 因此將它從SpringApp移動到DummyApplication

老實說,解決這個問題最簡單、最干凈的方法是使用 ApplicationContextAware,如下所示:

/** In a perfect world, this wouldn't exist. Maybe one day we can spring-ify everything and this won't need to. */
@Component
public class SpringContext implements ApplicationContextAware {
    private static ApplicationContext context;

    public static <T extends Object> T getBean(Class<T> beanClass) {
        return context.getBean(beanClass);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContext.context = applicationContext;
    }
}

然后,您可以在遺留代碼的構造函數中調用它來檢索您需要的內容:

    public LegacyCode() {
        sender = SpringContext.getBean(MessageSender.class);
    }

...它有效。

好的,您現在依賴於這個 SpringContext 類,但是如果您對整個應用程序進行 Spring-ify 並且它不是那么糟糕,那么這將及時發生。

但如果有人有更好的想法,請提供一個,我會審查。 謝謝。

我沒有克隆你的項目,只是開始在瀏覽器中快速查看你的 POM。 立即跳到我身上的是這樣的:

您的 Maven POM 是錯誤的。 您只需在pluginManagement部分中預配置 AspectJ Maven 插件,而無需在常規plugins部分中實際聲明插件。 即,在您的構建期間不會使用該插件。

如果修復后你仍然有后續問題,我可以再看看。


更新:我之前說的是真的,但我也注意到你的 POM 中有更多的疏忽:

  • 您使用了一個不存在的 AspectJ Maven 插件版本。
  • 對於編譯時編織,您需要類路徑上的 AspectJ 運行時aspectjrt
  • 依賴列表中需要spring-tx ,否則找不到spring-aspects引用的類。
  • 您的測試期望結果與實際的“ok”不同。

更新 2:您可以簡單地接受 此拉取請求

暫無
暫無

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

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