Fasulye başlatma işlemi tamamlandıktan sonra bir yöntem nasıl çağrılır?


237

Ben sadece bir kez ApplicationContext yükü, fasulye (statik olmayan) bir yöntem çağırmanız gereken bir kullanım durumu var. Bunun için MethodInvokingFactoryBean kullanırsam, sorun değil mi? Yoksa daha iyi bir çözümümüz var mı?

Yan not olarak, Web bağlamında Uygulama Bağlamını yüklemek için ConfigContextLoaderListener kullanıyorum. Ve 'A' fasulyesi somutlaştırılırsa, bir kez methodA () çağrılmasını isteyin.

Bu nasıl güzelce yapılabilir?

Yanıtlar:


196

Şöyle bir şey kullanabilirsiniz:

<beans>
    <bean id="myBean" class="..." init-method="init"/>
</beans>

Bu, fasulye başlatıldığında "init" yöntemini çağırır.


15
PostCastruct çoğu durumda daha iyi olmalı, çünkü bahar fasulyesi başlatma ile uğraşmak istemiyoruz.
lwpro2

4
@ lwpro2 "Bahar fasulyesi başlatmasıyla uğraşmak istemiyorum" ile ne demek istiyorsun?
Yngve Sneen Lindal

@Mercer Traieste Burada sınıf özelliği için ne vermeliyim? Burada denetleyici sınıfını verebilir miyim?
KJEjava48

314

Diğer yanıtlarda @PostConstruct önerisini genişletmek için, bu gerçekten en iyi çözüm, bence.

  • Kodunuzu Bahar API'sından ayırır (@PostConstruct javax'tadır. *)
  • Bu, init yönteminizi fasulyeyi başlatmak için çağrılması gereken bir şey olarak açıkça ekler
  • Bahar fasulyesi tanımınıza init-metodu özniteliğini eklemeyi hatırlamanız gerekmez, bahar otomatik olarak metodu çağırır (ek açıklama-config seçeneğini zaten bağlamda başka bir yere kaydettiğiniz varsayılarak).

9
Teşekkürler, bu işe yarıyor. Spring ile birlikte kullanmak istiyorsanız, CommonAnnotationBeanPostProcessor fasulyesini (yukarıda belirtildiği gibi) kaydetmek için "<context: annotation-config />" ifadesini eklemeniz gerektiğini unutmayın
khylo

2
Uygun olanı <context:component-scan>da işe yarar ve sınıf yolunuzda büyük Bahar dışı kitaplıklarınız varsa başlangıç ​​zamanını azaltmak için yararlı olabilir.
Donal Fellows

5
PostConstruct için JavaDoc, sınıf başına yalnızca bir yöntemin açıklanabileceğini söylüyor: docs.oracle.com/javaee/5/api/javax/annotation/…
Andrew Swan


2
@PostConstruct, somutlaştırdığınız fasulye kendi sınıfınız değil, bazı üçüncü taraf sınıfları ise size çok fazla fayda sağlamaz
John Rix

102

Referansta açıklandığı gibi dikkate alınması gereken üç farklı yaklaşım vardır

İnit-yöntemi niteliğini kullan

Artıları:

  • Bir arayüz uygulamak için fasulye gerektirmez.

Eksileri:

  • Fasulyenin doğru yapılandırıldığından emin olmak için inşaattan sonra bu yönteme derhal bir gerek yoktur.

Başlangıç ​​durumuna getirmeBean

Artıları:

  • İnit yöntemini belirtmeye veya bileşen tarama / ek açıklama işlemeyi açmaya gerek yoktur.
  • Bu kütüphaneyi kullanan uygulamanın fasulye yaşam döngüsüyle ilgilenmesini istemediğimiz bir kütüphane ile birlikte temin edilen fasulye için uygundur.

Eksileri:

  • İnit yöntemi yaklaşımından daha invaziv.

JSR-250 @PostConstruct lifecyle ek açıklamasını kullanın

Artıları:

  • Fasulyeleri otomatik olarak algılamak için bileşen tarama kullanılırken kullanışlıdır.
  • Başlatma için belirli bir yöntemin kullanılması gerektiğini netleştirir. Niyet, koda daha yakın.

Eksileri:

  • Başlatma artık yapılandırmada merkezi olarak belirtilmedi.
  • Ek açıklama işlemini (bazen unutulabilir) açmayı unutmamalısınız

4
@PostConstructBaşlangıçta işlemin sonunda çağıran yönteme ihtiyaç duyduğu için sınıfın bir parçası olduğu için gerçekten iyi bir şey olduğunu düşünüyorum.
Donal Bursiyerleri

Eğer bu sınıf GERÇEKTEN ona ihtiyaç duyuyorsa ve yapıcıda yapamazsanız, kod kokusu olduğunu düşündüğümden daha fazla.
user482745

39

Uygulamayı denedin InitializingBeanmi? Tamamen peşinde olduğunuz gibi geliyor.

Dezavantajı, fasulyenizin Bahar farkında olması, ancak çoğu uygulamada o kadar da kötü değil.


2
XML'de bir init yöntemi belirlemek yerine arabirimi uygulamayı seçmenizin bir nedeni var mı?
Mark

4
Bu bir zevk meselesi. Arayüz, Spring bileşen modelinin bir parçasıdır ve sadece bu amaca hizmet ederken, özel bir adlandırılmış yöntem için, bileşen yaşam döngüsünü tamamlamak için çağrılması gerektiği açık olmayabilir. Bu esas olarak iletişime hizmet eder. Tabii ki Bahar çerçevesine getirilen bağımlılığın dezavantajı ile. Aralarında güzel bir yol, açık anlambilime sahip olduğu, ancak bağımlılığı
tanımadığı için @PostConstruct'ın kullanılmasıdır

7
Oliver bana bazı güzel mazeretler veriyor, ama gerçekten sadece init yöntemi unutmuştum :) Başka bir nedeni, türün kendisinin tüm özellikler ayarlandıktan sonra "bitmiş" olması gerektiğini bilmesi - değil temelde konfigürasyonda olması gereken bir şey .
Jon Skeet

8

Bunu yapmak için uygulama bağlamınızda özel bir BeanPostProcessor dağıtabilirsiniz . Ya da çekirdeğinizde bir Spring arabirimi uygulamanın bir sakıncası yoksa, InitializingBean arabirimini veya "init-method" yönergesini (aynı bağlantı) kullanabilirsiniz.


Herkes BeanPostProcessor yazma hakkında ayrıntıları var mı. Tam olarak ihtiyacım olan şey bu. Şerefe :)
peakit

Birçok örnekle bahar gemileri. BeanPostProcessor için JavaDoc API'sine bakın ve birçok uygulama sınıfına bağlantılar bulacaksınız. Sonra onlar için kaynak koduna bakın.
Rob H

-7

İki yaklaşımla ilgili herhangi bir karışıklığı daha da netleştirmek için

  1. @PostConstruct ve
  2. init-method="init"

Kişisel deneyimlerime dayanarak, (1) kullanmanın yalnızca sunucu uygulaması kapsayıcısında çalıştığını, (2) ise masaüstü uygulamalarında bile her ortamda çalıştığını fark ettim. Yani, eğer bağımsız bir uygulamada Spring'i kullanacak olursanız, (2) 'yi başlattıktan sonra bu yöntemi çağırmak için kullanmalısınız.


4
Teknik olarak, @PostConstruct(Bahar tabanlı bir uygulamada kullanıldığında), sahip olunan Bahar bağlamının ömrüne bağlıdır. Bu bağlamlar her türlü uygulamada kullanılabilir.
Donal Fellows

Ben bekliyordum ama benim için çalışmadı davranış oldu.
Ayorinde
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.