Spring @PostConstruct so với thuộc tính init-method


103

Có sự khác biệt nào giữa việc sử dụng @PostConstructchú thích và khai báo cùng một phương thức như init-methodtrong cấu hình Spring XML không?

Câu trả lời:


153

Không thực tế, tôi không nghĩ rằng có bất kỳ sự khác biệt nào nhưng có những ưu tiên trong cách họ làm việc. @PostConstruct, init-methodlà BeanPostProcessors.

  1. @PostConstructlà một chú thích JSR-250 trong khi init-methodSpring là cách có một phương thức khởi tạo.
  2. Nếu bạn có một @PostConstructphương thức, nó sẽ được gọi trước khi các phương thức khởi tạo được gọi.
  3. Nếu bean của bạn thực hiện InitializingBean và ghi đè afterPropertiesSet, đầu tiên @PostConstructđược gọi, sau đó là afterPropertiesSetvà sau đó init-method.

Để biết thêm thông tin, bạn có thể kiểm tra tài liệu tham khảo của Spring .

Trước khi có thông số kỹ thuật JSR 250, cách sử dụng init-method trong xml được ưu tiên hơn, vì nó tách các lớp java (bean) khỏi bất kỳ lớp / chú thích cụ thể nào của mùa xuân. thì việc sử dụng phương thức init được ưu tiên hơn. Trong quá trình tạo phương thức, u có thể chỉ định phương thức cần được gọi là phương thức khởi tạo.

Bây giờ với việc giới thiệu các thông số kỹ thuật JSR 250 trong Java EE và hỗ trợ mùa xuân của các chú thích này, sự phụ thuộc vào khuôn khổ mùa xuân đã được giảm thiểu ở một mức độ nhất định.

Nhưng tôi phải thừa nhận rằng việc bổ sung những thứ này làm tăng khả năng đọc mã. Vì vậy, cả hai cách tiếp cận đều có những ưu và khuyết điểm.


22
Nếu một bean đang sử dụng nhiều hơn một trong những phương thức đó và dựa vào thứ tự khởi tạo, nó sẽ rất phức tạp và không thể hiểu được.
Nghiên cứu sinh Donal

2
@Donal Hoàn toàn đúng. Chỉ cung cấp thông tin về cách hoạt động của nó.
Aravind A

1
Có một sự khác biệt quan trọng: Bạn cần phải mùa xuân đặc biệt cấu hình để chú thích quá trình làm @PostConstruct công việc: stackoverflow.com/q/3434377/134898
Juan Calero

@DonalFellows, nhưng bạn cần biết điều này nếu bạn dự định tham gia các kỳ thi lấy chứng chỉ;)
S.Klechkovski

@DonalFellows - Bạn có thể vui lòng giải thích câu trả lời của mình không? Ý tôi là những khó khăn phải đối mặt nếu một bean dựa vào thứ tự khởi tạo. Thực ra tôi muốn biết cái nào tốt hơn. PostConstruct hoặc Bean (initMethod = "init") để thực hiện một số nội dung khởi tạo từ bean trước khi nó phục vụ bất kỳ yêu cầu nào?
Ayaskant

19

Không có sự khác biệt thực sự. Nó phụ thuộc vào cách bạn muốn cấu hình hệ thống của mình và đó là vấn đề của sự lựa chọn cá nhân. Bản thân tôi, tôi thích sử dụng @PostConstructcác chú thích cho mã của riêng mình (vì bean chỉ được định cấu hình chính xác sau khi phương thức được gọi) và tôi sử dụng init-methodkhi khởi tạo các bean từ các thư viện không phải là Spring (tất nhiên không thể áp dụng các chú thích ở đó!) nhưng tôi hoàn toàn có thể hiểu mọi người muốn làm theo cách này hay cách khác.


4

@postconstruct không phải là một phần của mùa xuân. Nó là một phần của gói javax. Cả hai đều giống nhau. bằng cách sử dụng init-method, chúng tôi cần thêm vào tệp xml. Nếu bạn sử dụng @postconstruct, việc thêm trong xml là không bắt buộc. Kiểm tra bài viết dưới đây.

http://answersz.com/spring-postconstruct-and-predestroy/


3

Như bạn có thể thấy trong sơ đồ bên dưới của Gọi lại vòng đời tạo Bean .

Gọi lại vòng đời của Bean Creation

Bước 3 này xảy ra trong Gọi lại Vòng đời Tạo Bean:

  1. Nó được đề cập rằng @PostConstructsẽ được gọi.
  2. Nếu InitializingBeanđược thực hiện, sau đó afterPropertiesSet()sẽ được gọi.
  3. Nếu định nghĩa bean chứa init-methodhoặc @Bean(initmethod="..")thì nó gọi phương thức init.

Sơ đồ này là từ Pro Spring 5: Hướng dẫn chuyên sâu về Spring Framework và các công cụ của nó


3

thể có sự khác biệt giữa @PostConstructinit-methodbởi vì @PostConstructđược xử lý trong postProcessAfterInitializationgiai đoạn khởi tạo bean ( AbstractAutowireCapableBeanFactory.initializeBean()phương thức) bởi CommonAnnotationBeanPostProcessor, trong khi initphương thức được gọi sau khi hoàn thành postProcessBeforeInitializationgiai đoạn (và, đối với vấn đề này, trước khi bắt đầu postProcessAfterInitializationgiai đoạn).
CHỈNH SỬA : Vì vậy, trình tự là: 1) postProcessBeforeInitializationpha, 2) initphương thức được gọi, 3) postProcessAfterInitializationpha, gọi @PostConstructphương thức

(Như một lưu ý phụ, một tuyên bố từ câu trả lời được chấp nhận

@PostConstruct, init-method là BeanPostProcessors

không hoàn toàn đúng: @PostConstructđược xử lý bởi một BeanPostProcessor, initphương thức thì không.)

Sẽ sự khác biệt nếu một số (có thể tùy chỉnh) BeanPostProcessor, được cấu hình với ( Ordered.getOrder()) để được thực thi sau đó CommonAnnotationBeanPostProcessor, đang thực hiện một điều gì đó nghiêm trọng trong postProcessBeforeInitializationphương thức của nó .
Không bất kỳ sự khác biệt nào với cấu hình Spring mặc định BeanPostProcessorsbởi vì tất cả BeanPostProcessorscấu hình được cấu hình để được thực thi sau đó CommonAnnotationBeanPostProcessor, không thực hiện bất kỳ điều gì trong postProcessBeforeInitializationphương thức.

Tóm lại, câu trả lời được chấp nhận và câu trả lời tương tự là đúng ... trong 99% trường hợp, và bài đăng này chỉ để tôn vinh một khái niệm "ma quỷ là chi tiết"


Chào! Điều này thật khó hiểu, nếu PostConstruct chạy trước init-method, thì nó sẽ được xử lý như thế nào bởi postProcessAfterInitialization nếu phương thức init chạy sau postProcessBeforeInitialization và trước postProcessAfterInitialization ???
Maxrunner

@Maxrunner, xin lỗi vì sự nhầm lẫn và rất cảm ơn bạn đã cho biết! Trên thực tế, tôi chưa bao giờ có ý nói rằng PostConstruct chạy trước init-method. Dù sao, tôi đã cập nhật câu trả lời của mình với một số giải thích
igor.zh

2

Mã đầy đủ tại đây: https://github.com/wkaczurba/so8519187 ( spring-boot )

Sử dụng chú thích:

@Slf4j
@Component
public class MyComponent implements InitializingBean {

    @Value("${mycomponent.value:Magic}")
    public String value;

    public MyComponent() {
        log.info("MyComponent in constructor: [{}]", value); // (0) displays: Null
    }

    @PostConstruct
    public void postConstruct() {
        log.info("MyComponent in postConstruct: [{}]", value); // (1) displays: Magic
    }

    @Override // init-method; overrides InitializingBean.afterPropertiesSet()
    public void afterPropertiesSet() {
        log.info("MyComponent in afterPropertiesSet: [{}]", value);  // (2) displays: Magic
    }   

    @PreDestroy
    public void preDestroy() {
        log.info("MyComponent in preDestroy: [{}]", value); // (3) displays: Magic
    }
}

Cho chúng tôi:

Đang làm mới org.springframework.context ...

MyComponent trong constructor: [null]
MyComponent trong postConstruct: [Magic]
MyComponent trong afterPropertiesSet: [Magic]
...

Đăng ký bean để hiển thị JMX khi khởi động Đã
bắt đầu DemoApplication trong 0,561 giây (JVM chạy cho 1.011)
Đóng org.springframework.context .. . Hủy đăng ký đậu tiếp xúc với JMX khi tắt máy

...
MyComponent trong preDestroy: [Magic]

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.