Spring @PostConstruct vs. atribut metode-init

103

Apakah ada perbedaan antara menggunakan @PostConstructanotasi dan mendeklarasikan metode yang sama seperti init-methoddi konfigurasi Spring XML?

Jan Zyka
sumber

Jawaban:

153

Tidak, secara praktis saya tidak berpikir ada perbedaan tetapi ada prioritas dalam cara kerjanya. @PostConstruct, init-methodadalah BeanPostProcessors.

  1. @PostConstruct adalah anotasi JSR-250 sementara init-method cara Spring memiliki metode inisialisasi.
  2. Jika Anda memiliki @PostConstructmetode, ini akan dipanggil terlebih dahulu sebelum metode inisialisasi dipanggil.
  3. Jika bean Anda mengimplementasikan InitializingBean dan menimpa afterPropertiesSet, yang pertama @PostConstructdipanggil, lalu afterPropertiesSetkemudian init-method.

Untuk info lebih lanjut, Anda dapat memeriksa dokumentasi referensi Spring .

Sebelum spesifikasi JSR 250, penggunaan metode-init dalam xml lebih disukai, karena ia memisahkan kelas java (kacang) dari kelas / anotasi khusus pegas apa pun. Jadi, jika Anda membangun pustaka yang tidak perlu bergantung pada kacang infrastruktur pegas maka penggunaan metode init lebih disukai. Selama metode pembuatan, Anda dapat menentukan metode yang perlu disebut sebagai metode inisialisasi.

Sekarang dengan diperkenalkannya spesifikasi JSR 250 di Java EE dan dukungan pegas untuk anotasi ini, ketergantungan pada kerangka pegas telah dikurangi sampai batas tertentu.

Tetapi saya harus mengakui bahwa penambahan hal-hal ini meningkatkan keterbacaan kode. Jadi ada pro dan kontra dari kedua pendekatan tersebut.

Aravind A
sumber
23
Jika kacang menggunakan lebih dari satu metode tersebut dan mengandalkan urutan inisialisasi, itu akan menjadi sangat rumit dan tidak dapat dipertahankan.
Donal Fellows
2
@Pribadi Cukup benar. Hanya memberikan info tentang cara kerjanya.
Aravind A
1
Ada perbedaan penting: Anda perlu secara khusus mengonfigurasi Spring untuk memproses anotasi agar @PostConstruct berfungsi: stackoverflow.com/q/3434377/134898
Juan Calero
@DonalFellows, tetapi Anda perlu mengetahui ini jika Anda berencana untuk mengikuti ujian sertifikasi;)
S.Klechkovski
@DonalFellows - Bisakah Anda menjelaskan jawaban Anda? Yang saya maksud adalah kesulitan yang dihadapi jika sebuah bean mengandalkan urutan inisialisasi. Sebenarnya saya ingin tahu mana yang lebih baik. PostConstruct atau Bean (initMethod = "init") untuk melakukan beberapa hal inisialisasi dari bean sebelum melayani permintaan?
Ayaskant
19

Tidak ada perbedaan nyata. Terserah bagaimana Anda lebih suka mengonfigurasi sistem Anda, dan itu masalah pilihan pribadi. Saya sendiri, saya lebih suka menggunakan @PostConstructanotasi untuk kode saya sendiri (karena kacang hanya dikonfigurasi dengan benar setelah metode dipanggil) dan saya gunakan init-methodsaat membuat instance kacang dari pustaka non-Spring-aware (tidak dapat menerapkan anotasi di sana, tentu saja!) tetapi saya benar-benar dapat memahami orang-orang yang ingin melakukannya dengan satu atau lain cara.

Donal Fellows
sumber
4

@postconstruct bukan bagian dari pegas. Ini adalah bagian dari paket javax. Keduanya sama. menggunakan metode-init kita perlu menambahkan dalam file xml. Jika Anda menggunakan @postconstruct menambahkan xml tidak diperlukan. Simak artikel di bawah ini.

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

Amruth M Raj
sumber
3

Seperti yang Anda lihat pada diagram di bawah ini dari Bean Creation Life-Cycle Callback .

Callback Siklus Hidup Pembuatan Kacang

Langkah 3 ini terjadi di Panggilan Balik Siklus Hidup Bean Creation:

  1. Disebutkan bahwa @PostConstructakan dipanggil.
  2. Jika InitializingBeandiimplementasikan, maka afterPropertiesSet()akan dipanggil.
  3. Jika definisi kacang mengandung init-methodatau @Bean(initmethod="..")kemudian memanggil metode init.

Diagram ini berasal dari Pro Spring 5: An In-Depth Guide to Spring Framework dan Tools Its

yashjain12yj
sumber
3

Ada mungkin perbedaan antara @PostConstructdan init-methodkarena @PostConstructditangani di postProcessAfterInitializationfase inisialisasi kacang ( AbstractAutowireCapableBeanFactory.initializeBean()metode) oleh CommonAnnotationBeanPostProcessor, sedangkan initmetode dipanggil setelah selesainya postProcessBeforeInitializationfase (dan, dalam hal ini, sebelum awal postProcessAfterInitializationfase).
EDIT : Jadi, urutannya adalah: 1) postProcessBeforeInitializationfase, 2) initmetode dipanggil, 3) postProcessAfterInitializationfase, yang memanggil @PostConstructmetode

(Sebagai catatan tambahan, pernyataan dari jawaban yang diterima

@PostConstruct, init-method adalah BeanPostProcessors

tidak sepenuhnya benar: @PostConstructditangani oleh BeanPostProcessor, initmetode tidak.)

Akan ada perbedaan jika beberapa (berpotensi kustom) BeanPostProcessor, yang dikonfigurasi dengan ( Ordered.getOrder()) untuk dieksekusi setelah CommonAnnotationBeanPostProcessor, melakukan sesuatu yang serius dalam postProcessBeforeInitializationmetodenya.
Tidak ada perbedaan apapun dengan konfigurasi Spring default BeanPostProcessorskarena semua BeanPostProcessorsyang dikonfigurasi untuk dijalankan setelahnya CommonAnnotationBeanPostProcessor, tidak melakukan apa pun dalam postProcessBeforeInitializationmetode.

Kesimpulannya, jawaban yang diterima dan yang serupa adalah benar ... dalam 99% kasus, dan posting ini hanya untuk memberi penghormatan pada konsep "iblis ada dalam detail"

igor.zh
sumber
Hai! Ini membingungkan, jika PostConstruct berjalan sebelum metode init, bagaimana cara menangani postProcessAfterInitialization jika metode init berjalan setelah postProcessBeforeInitialization dan sebelum postProcessAfterInitialization ???
Maxrunner
@Maxrunner, maaf atas kebingungannya dan banyak terima kasih telah memberi tahu! Sebenarnya, saya tidak pernah bermaksud mengatakan bahwa PostConstruct berjalan sebelum init-method. Bagaimanapun, saya memperbarui jawaban saya dengan beberapa klarifikasi
igor.zh
2

Kode lengkap di sini: https://github.com/wkaczurba/so8519187 ( musim semi-boot )

Menggunakan anotasi:

@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
    }
}

Memberi kami:

Menyegarkan org.springframework.context ...

MyComponent dalam konstruktor: [null]
MyComponent di postConstruct: [Magic]
MyComponent di afterPropertiesSet: [Magic]
...

Mendaftarkan kacang untuk eksposur JMX saat startup
Memulai DemoApplication dalam 0,561 detik (JVM berjalan selama
1,011 ) Menutup org.springframework.context .. . Membatalkan pendaftaran kacang yang terkena JMX saat dimatikan

...
MyComponent di preDestroy: [Magic]

Witold Kaczurba
sumber