Spring @PostConstruct ve init-method özniteliği karşılaştırması


103

@PostConstructEk açıklamayı kullanmak init-methodile Spring XML yapılandırmasında olduğu gibi aynı yöntemi bildirmek arasında herhangi bir fark var mı ?

Yanıtlar:


153

Hayır, pratikte bir fark olduğunu düşünmüyorum ama çalışma şekillerinde öncelikler var. @PostConstruct, init-methodBeanPostProcessors.

  1. @PostConstructbir JSR-250 ek açıklaması iken init-method, Spring'in bir başlatma yöntemine sahip olma şeklidir.
  2. Bir @PostConstructyönteminiz varsa, bu, başlatma yöntemleri çağrılmadan önce çağrılacaktır.
  3. Eğer fasulyeniz InitializingBean uyguluyorsa ve geçersiz kılarsa afterPropertiesSet, önce @PostConstructçağrılır, sonra afterPropertiesSetve sonra init-method.

Daha fazla bilgi için Spring'in referans belgelerine bakabilirsiniz .

JSR 250 spesifikasyonlarından önce, java sınıflarını (fasulye) herhangi bir yaya özgü sınıflardan / ek açıklamalardan ayırdığı için xml'de init yönteminin kullanılması tercih ediliyordu. daha sonra init yönteminin kullanılması tercih edildi. u oluşturma yöntemi sırasında başlatma yöntemi olarak çağrılması gereken yöntemi belirtebilirsiniz.

Şimdi Java EE'de JSR 250 spesifikasyonlarının eklenmesi ve bu açıklamaların yay desteğiyle, yay çerçevesine bağımlılık bir dereceye kadar azaltıldı.

Ancak itiraf etmeliyim ki bu şeylerin eklenmesi kodun okunabilirliğini arttırır, yani her iki yaklaşımın da artıları ve eksileri vardır.


23
Bir fasulye bu yöntemlerden birden fazlasını kullanıyorsa ve başlatma sırasına bağlıysa, korkunç derecede karmaşık ve sürdürülemez olacaktır.
Donal Fellows

2
@Donal Oldukça doğru. Sadece bunun nasıl çalıştığı hakkında bilgi veriyordu.
Aravind A

1
Önemli bir fark var: Spring'i, @PostConstruct'ın çalışması için ek açıklamaları işleyecek şekilde özel olarak yapılandırmanız gerekir: stackoverflow.com/q/3434377/134898
Juan Calero

@DonalFellows, ancak sertifika sınavlarına
girmeyi

@DonalFellows - Cevabınızı açıklar mısınız? Bir fasulyenin başlatma sırasına bağlı olması durumunda karşılaşılan zorlukları kastediyorum. Aslında hangisinin daha iyi olduğunu bilmek istiyorum. PostConstruct veya Bean (initMethod = "init") herhangi bir isteği yerine getirmeden önce bir çekirdekten bazı başlatma işlemleri yapmak için?
Ayaskant

19

Gerçek bir fark yok. Sisteminizi nasıl yapılandırmayı tercih ettiğinize bağlıdır ve bu kişisel bir seçim meselesidir. Ben @PostConstructde kendi kodum için ek açıklamaları kullanmayı tercih ederim (çünkü çekirdek yalnızca yöntem çağrıldıktan sonra doğru şekilde yapılandırılır) ve init-methodBahar ile uyumlu olmayan kitaplıklardan fasulye örneğini oluştururken kullanırım (elbette notları orada uygulayamam!) ama her şeyi öyle ya da böyle yapmak isteyen insanları tamamen anlayabiliyorum.



3

Aşağıdaki Bean Creation Life-Cycle Callback şemasında görebileceğiniz gibi .

Bean Oluşturma Yaşam Döngüsü Geri Çağırma

Bu 3 adım Bean Creation Life-Cycle Callback'te gerçekleşir:

  1. Çağrılacağı belirtiliyor @PostConstruct.
  2. Uygulanırsa InitializingBean, afterPropertiesSet()çağrılacaktır.
  3. Fasulye tanımı içeriyorsa init-methodveya @Bean(initmethod="..")daha sonra init yöntemini çağırır.

Bu şema Pro Spring 5'ten alınmıştır: Yay Çerçevesi ve Araçlarına Yönelik Kapsamlı Bir Kılavuz


3

Orada olabilir arasındaki farkı @PostConstructve init-methodçünkü @PostConstructiçinde ele alınır postProcessAfterInitializationfasulye başlatma (aşamasından AbstractAutowireCapableBeanFactory.initializeBean()tarafından yöntemi) CommonAnnotationBeanPostProcessorise, inityöntem tamamlandıktan sonra çağrılan postProcessBeforeInitializationfazda (bu konuda ve başlangıcından önce, postProcessAfterInitializationfaz).
DÜZENLEME : Yani, sıra şu şekildedir : 1) postProcessBeforeInitializationaşama, 2) inityöntem çağrılır, 3) postProcessAfterInitializationaşama, @PostConstructyöntemi çağırır

(Yan not olarak, kabul edilen cevaptan bir açıklama

@PostConstruct, init yöntemi BeanPostProcessors'tır

tam olarak doğru değil: @PostConstructa tarafından işleniyor BeanPostProcessor, inityöntem değil.)

Daha sonra çalıştırılmak üzere ( ) ile yapılandırılan bazılarının (potansiyel olarak özel) yönteminde ciddi bir şey yapması durumunda fark olacaktır . Orada hayır varsayılan Bahar yapılandırma ile herhangi bir farklılık çünkü tüm sonra uygulanmak üzere konfigüre edildiği , içinde bir şey yapmayın yöntemle.BeanPostProcessorOrdered.getOrder()CommonAnnotationBeanPostProcessorpostProcessBeforeInitialization
BeanPostProcessorsBeanPostProcessorsCommonAnnotationBeanPostProcessorpostProcessBeforeInitialization

Sonuç olarak, kabul edilen cevap ve benzerleri doğrudur ... vakaların% 99'unda ve bu gönderi sadece "şeytan ayrıntıda gizlidir" kavramına bir haraç ödemektir.


Selam! Bu kafa karıştırıcıdır, eğer PostConstruct init yönteminden önce çalışıyorsa, init yöntemi postProcessBeforeInitialization'dan sonra ve postProcessAfterInitialization'dan önce çalışıyorsa postProcessAfterInitialization tarafından nasıl işlenir ???
Maxrunner

@Maxrunner, karışıklık için özür dilerim ve bildirdiğiniz için çok teşekkürler! Aslında, PostConstruct'ın init-method'tan önce çalıştığını asla söylemedim. Her neyse, cevabımı bazı açıklamalarla güncelledim
igor.zh

2

Tam kod burada: https://github.com/wkaczurba/so8519187 ( yaylı önyükleme )

Ek açıklamaları kullanma:

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

Bizi alır:

Org.springframework.context yenileniyor ...


Yapıcıda MyComponent : [null] postConstruct'ta [null] MyComponent: [Magic]
AfterPropertiesSet içinde MyComponent: [Magic]
...

Başlangıçta JMX pozlaması için fasulye kaydediliyor
DemoApplication 0,561 saniyede başlatıldı (JVM 1.011 için çalışıyor)
org.springframework.context kapatılıyor .. . Kapatma sırasında JMX'e maruz kalan çekirdeklerin kaydı siliniyor

...
Ön Yıkımda MyComponent: [Magic]

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.