Not : Dependency Injection sınıflar arasındaki bağımlılığı azaltırken altyapıya olan bağımlılığı
artıyor.
Dependency injection increases coupling by requiring the user of a subsystem to provide for the needs of that subsystem.
1. Spring İçindeki Olayları Dinlemek
Spring Container da diğer tüm container tarzı
yazılımlar gibi, kendisine abone olunup Observer tasarım örüntüsünün
kullanılmasına imkan tanımaktadır. Bu durumu gösteren şekli buradan
aldım. Böylece
ApplicationListener arayüzü vasıtasıyla bir çok olayı öğrenmek
mümkün.
2. Spring ve Bean'lerin Yaratılması
2.1 Bean Yaratılmadan Önce
Aşağıdaki şekli
buradan aldım. Bean yaratılmadan önce BeanFactoryPostProcessor ile bean tanımında değişiklik yapabilmek mümkün.
Aşağıdaki
şekilde ise BeanFactoryPostProcessor arayüzünden türeyen bazı sınıfları görmek mümkün.
2.2 Bean Yaratıldıktan Sonra
Spring içindeki bean'lerin yaşam döngüsünü (lifecycle) bir nebzeye
kadar detaylandırmak mümkün. Bunun için kullanılabilecek 3 yöntem var.
- BeanPostProcessor Yöntemi
- XML içinde Custom Metod Yöntemi
- InitializingBean ve DisposableBean Yöntemi
BeanPostProcessor Yöntemi
Bu başlığı ikiye ayırmak lazım. Birincisi Spring içinde tanımlı olan BeanPostProcessor sınıfları, ikincisi ise kendi tanımladığımız sınıflar.
Spring içinde tanımlı olan BeanPostProcessor sınıfları
BeanPostProcessorYöntemi
burada anlatılıyor. Örneğin
<tx:annotation-driven> XML cümlesi ile BeanPostProcessor yöntemi aracılığıyla transaction yönetimi
gerçekleştiriliyor. Bir bean yaratılmadan önce bir BeanPostProcessor @Transactional anotasyonu kullanılmışmı diye kontrol ediyor ve eğer kullanılmışsa yaratılmak istenen bean için bir
proxy üretiyor.
Bir başka örnek olarak
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor sınıfına da bakılabilir. Bu sınıf ile ilgili güzel bir örnek te
burada bulunabilir.
Bu sınıf sayesinde
@Autowired,
@Inject,
@Resource gibi tagler kullanılabiliyor.
Bu sınıfı Spring'e dahil etmek için
<context:annotation-config /> veya
<context:component-scan> XML cümlelerini eklemek yeterli. Bu ikisi arasındaki farkı anlamak için
Difference between <context:annotation-config> vs <context:component-scan> başlıklı yazıya bakabilirsiniz.
<context:component-scan> ile @Component, @Repository, @Service ve @Controller olarak işaretli bean'ler Spring'e dahil ediliyor. Eğer bu taglerden bazılar hariç bırakılmak istenirse aşağıdaki gibi
yapılabilir.
<
context:
component-scan base-package=
"com.java.test.app org.java.support">
<
context:exclude-filter type=
"annotation" expression=
"org.springframework.stereotype.Repository"/>
</
context:
component-scan>
Kendi Tanımladığımız BeanPostProcessor Sınıfları
Buradaki örnekte Spring ile yaratılan bir bean nesnesinin Guava EventBus nesnesine eklenmesi örneği var.
Custom Metod Yöntemi
Bu yöntemde XML içinde bean'in çağırılacak metodu belirtliyor.
InitializingBean ve DisposableBean Yöntemi
Bu yöntemde bean
InitializingBean ve
DisposableBean arayüzlerinde türetiliyor.
Yöntemler
arasında öncelik sırası bulunmakta. Bu öncelik sırasını gösteren bir
şekli
burada buldum.
Görüldüğü gibi
InitializingBean arayüzü tarafından istenen afterPropertiesSet() metodu custom init metodundan
önce çağırılır. Aynı zamanda
DisposableBean arayüzü tarafından istenen destroy() metodu da yine custom destroy metodundan
önce çağırılır.
Benzer bir şekli ise
burada buldum.
InitializingBean yöntemi Spring'e mahsus.
JSR-250 ile
@PostConstruct ve @PreDestroy tagleri tanımlanmış.
Using JSR-250's @PostConstruct Annotation to Replace Spring's InitializingBean başlıklı yazıda da anlatıldığı gibi Spring'e mahsus bu arayüzler yerine @PostConstruct ve @PreDestroy anotasyonlarının kullanımı tercih edilmelidir.
2.3 new() ile Yaratılan Bean'ler
How to inject dependencies into a self-instantiated object in Spring? sorusunda da cevaplandığı gibi
AutowireCapableBeanFactory arayüzü kullanılarak manuel olarak yaratılmış olan bir bean'e de dependency injekte edilebilir.
2.4 Bean ve Yaratılış Kapsamı (Scope)
Spring ile default gelen scope singleton scope'tur. Yani container bir bean'i bir defa yarattıktan sonra onu önbellekte saklar ve tekrar istenirse yine aynı nesneyi döndürür. Bu durum gösteren bir şekli buradan aldım.
Konuyu daha iyi açıklayan bir örneği ise
burada bulabilirsiniz.