在另一个 bean 的构造函数中引用时,@Autowired bean 为空

下面显示的是我尝试引用 ApplicationProperties bean 的代码片段。当我从构造函数引用它时,它是空的,但是当从另一个方法引用它时,它是正常的。到目前为止,我还没有在其他类中使用这个自动连接的 bean 的问题。但这是我第一次尝试在另一个类的构造函数中使用它。

在 applicationProperties 下面的代码片段中,当从构造函数调用时,属性为空,但是当转换方法中引用时,属性不为空。我错过了什么

@Component
public class DocumentManager implements IDocumentManager {


private Log logger = LogFactory.getLog(this.getClass());
private OfficeManager officeManager = null;
private ConverterService converterService = null;


@Autowired
private IApplicationProperties applicationProperties;




// If I try and use the Autowired applicationProperties bean in the constructor
// it is null ?


public DocumentManager() {
startOOServer();
}


private void startOOServer() {
if (applicationProperties != null) {
if (applicationProperties.getStartOOServer()) {
try {
if (this.officeManager == null) {
this.officeManager = new DefaultOfficeManagerConfiguration()
.buildOfficeManager();
this.officeManager.start();
this.converterService = new ConverterService(this.officeManager);
}
} catch (Throwable e){
logger.error(e);
}
}
}
}


public byte[] convert(byte[] inputData, String sourceExtension, String targetExtension) {
byte[] result = null;


startOOServer();
...

下面是来自 ApplicationProperties 的片段..。

@Component
public class ApplicationProperties implements IApplicationProperties {


/* Use the appProperties bean defined in WEB-INF/applicationContext.xml
* which in turn uses resources/server.properties
*/
@Resource(name="appProperties")
private Properties appProperties;


public Boolean getStartOOServer() {
String val = appProperties.getProperty("startOOServer", "false");
if( val == null ) return false;
val = val.trim();
return val.equalsIgnoreCase("true") || val.equalsIgnoreCase("on") || val.equalsIgnoreCase("yes");
}
69540 次浏览

Autowiring (link from Dunes comment) happens after the construction of an object. Therefore they will not be set until after the constructor has completed.

If you need to run some initialization code, you should be able to pull the code in the constructor into a method, and annotate that method with @PostConstruct.

To have dependencies injected at construction time you need to have your constructor marked with the @Autowired annoation like so.

@Autowired
public DocumentManager(IApplicationProperties applicationProperties) {
this.applicationProperties = applicationProperties;
startOOServer();
}

Yes, both answers are correct.

To be honest, this problem is actually similar to the post Why is my Spring @Autowired field null? .

The root cause of the error can be explained in the Spring reference doc (Autowired) , as follow:

Autowired Fields

Fields are injected right after construction of a bean, before any config methods are invoked.

But the real reason behind this statement in Spring doc is the Lifecycle of Bean in Spring. This is part of Spring's design philosophy.

This is Spring Bean Lifecycle Overview: enter image description here Bean needs to be initialized first before it can be injected with properties such as field. This is how beans are designed, so this is the real reason.

I hope this answer is helpful to you!