[英]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 中有更多的疏忽:
aspectjrt
。spring-tx
,否則找不到spring-aspects
引用的類。更新 2:您可以簡單地接受 此拉取請求。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.