@ ถั่วอัตโนมัติเป็นโมฆะเมื่ออ้างถึงในตัวสร้างของถั่วอื่น


91

ด้านล่างนี้เป็นตัวอย่างโค้ดที่ฉันพยายามอ้างอิง ApplicationProperties 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");
  }

คำตอบ:


183

การเดินสายอัตโนมัติ (ลิงก์จากความคิดเห็นของ Dunes) เกิดขึ้นหลังจากการสร้างวัตถุ ดังนั้นพวกเขาจะไม่ถูกตั้งค่าจนกว่าตัวสร้างจะเสร็จสมบูรณ์

@PostConstructหากคุณจำเป็นต้องใช้รหัสเริ่มต้นบางอย่างที่คุณควรจะสามารถที่จะดึงรหัสในการสร้างลงในวิธีการและคำอธิบายวิธีการที่มี


3
ตามที่กล่าวไว้ในเอกสาร - static.springsource.org/spring/docs/2.5.x/api/org/…
Dunes

ขอบคุณสำหรับลิงค์ฉันจะเพิ่มเข้าไปในคำตอบเพื่อให้ค้นหาได้ง่าย
nicholas.hauschild

2
ขอบคุณฉันยังไม่พบข้อความสำคัญ "ฟิลด์ถูกฉีดทันทีหลังจากสร้างถั่ว ... " ฉันได้ลองใช้คำอธิบายประกอบ @PostConstruct แล้วและเป็นสิ่งที่ฉันต้องการจริงๆ
hairyone

จะเป็นการดีที่จะโพสต์ลิงก์เกี่ยวกับ @PostConstruct static.springsource.org/spring/docs/3.0.0.M3/reference/html/…
Timofey

@ ทิมขอบคุณ! ฉันอัปเดตลิงก์คำตอบไปยังเวอร์ชัน Spring 3.2 และฉันได้เพิ่มลิงก์เวอร์ชัน Spring 3.2 ของคุณด้วย
nicholas.hauschild

45

หากต้องการให้การพึ่งพาในเวลาก่อสร้างคุณต้องมีตัวสร้างของคุณที่ทำเครื่องหมายด้วย@Autowiredหมายเหตุดังนี้

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

2
อันที่จริงฉันคิดว่านี่น่าจะเป็นคำตอบที่ต้องการ แนวทางการฉีดแบบพึ่งพาตัวสร้างเหมาะอย่างยิ่งสำหรับส่วนประกอบที่จำเป็น การใช้แนวทางนี้ทำให้กรอบสปริงสามารถตรวจจับการขึ้นอยู่กับวงจรของส่วนประกอบต่างๆได้ (เช่นเดียวกับ A ขึ้นอยู่กับ B, B ขึ้นอยู่กับ C, C ขึ้นอยู่กับ A) รูปแบบการฉีดโดยใช้เซ็ตเทอร์หรือฟิลด์อัตโนมัติสามารถที่จะฉีดถั่วที่ไม่ได้เริ่มต้นอย่างสมบูรณ์ลงในฟิลด์ของคุณทำให้สิ่งต่าง ๆ ยุ่งขึ้นเล็กน้อย
Seakayone

0

ใช่คำตอบทั้งสองถูกต้อง

บอกตามตรงว่าจริงๆแล้วปัญหานี้คล้ายกับโพสต์เหตุใดฟิลด์ Spring @Autowired ของฉันจึงเป็นโมฆะ .

สาเหตุหลักของข้อผิดพลาดสามารถอธิบายได้ในเอกสารอ้างอิง Spring (แบบอัตโนมัติ ) ดังต่อไปนี้:

ฟิลด์อัตโนมัติ

ฟิลด์จะถูกฉีดทันทีหลังจากสร้าง bean ก่อนที่จะเรียกใช้วิธีการกำหนดค่าใด ๆ

แต่เหตุผลที่แท้จริงเบื้องหลังคำแถลงนี้ใน Spring doc คือLifecycle of Bean in Spring นี่เป็นส่วนหนึ่งของปรัชญาการออกแบบของ Spring

นี่คือ ภาพรวมวงจรชีวิตของ Spring Bean : ป้อนคำอธิบายภาพที่นี่ Bean ต้องได้รับการเริ่มต้นก่อนจึงจะสามารถฉีดด้วยคุณสมบัติเช่นฟิลด์ได้ นี่คือวิธีการออกแบบถั่วดังนั้นนี่คือเหตุผลที่แท้จริง

ฉันหวังว่าคำตอบนี้จะเป็นประโยชน์กับคุณ!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.