IoC ve DI prensiplerini anlattığım bir önceki yazıda IoC’yi interface kullanarak kendimiz yapmayı anlatmıştım.Spring Framework’de ise bu prensip IoC containerlar ile sağlanır. IoC containerların temel görevi beanleri yönetmektir. Yönetmek kelimesinin kapsamı ise geniştir. Beanleri oluşturmak, birbirleriyle uyumunu sağlamak, ayarlarını yapılandırmak, yaşam döngülerini kontrol etmek gibi işler yönetmek kelimesinin kapsamına girer. Bu noktada “bean nedir?” sorusunun da cevabını vermem gerekiyor. Bean standartları belirlenmiş bir Java classıdır. Normal classtan üç farkı vardır:
- Tüm değişkenleri private olmak zorunda. (Getter/Setter kullanmanız gerekiyor.)
- Parametresiz bir public constructor’ı olmak zorunda.
- Serializable interface’ini implemente etmek zorunda.
Yukarıdaki klasik bir IoC Container akış diyagramı var. Diyagram üzerinde çalışma akışı şöyledir:
Container, hazırladığımız POJO classlarını alır. Sonra bu POJO classlarını yönetmek ve konfigüre etmek için xml dosyalarından, anotasyonlardan ve beanlere yönelik hazırlanmış kodlardan gerekli metadatayı alır. Artık elinde hem POJO’lar hem de bu POJO’ları nasıl yöneceğinin bilgisi vardır. Bunun sonucunda IoC, programda kullanıma hazır beanleri yaratır. Bu beanleri yaratırken de IoC prensibini sağlamak için bir önceki yazıda bahsettiğimiz DI prensibini kullanır. Gerekli bağımlılıkları framework tarafındaki aktör olarak kendisi verir.
Spring container’ın ne işe yaradığını öğrendikten sonra irdelemeye devam edelim. İki tip Spring container vardır.
- BeanFactory Container
- ApplicationContextContainer
BeanFactory Spring Container’a DI desteği sağlayan en temel interface’tir. Beanleri oluşturmanın dışında konfigürasyonlarını yapar ve bağımlılıklarla birbirine bağlar. ApplicationContext’e göre biraz daha ilkel olduğu söylenebilir. Bu sebeple BeanFactory’i kısa kesip ApplicationContext’e geçiyorum.
ApplicationContext ApplicationContext, BeanFactory’nin tüm özelliklerini barındıran ve bunun yanında ekstra yetenekleri olan container’dır. Bu sebeple BeanFactory’e oranla daha çok kullanılıyor. Spring’in kendi dokümanı da bu tercihi destekliyor. Eğer gerçekten kullanmak için iyi bir sebebiniz yoksa ApplicationContext kullanın şeklinde bir ifade geçiyor. Bu sebebe örnek olarak ise kilobayt seviyesinde performans hassasiyeti sağlamanız gereken projeleri örnek verebiliriz. Onun dışında ApplicationContext kullanmak ve sunduğu ekstra özelliklerden faydalanmak daha doğru bir yaklaşım. ApplicationContext’in sunduğu ekstra özellikler bu aşamada biraz daha üst seviye sayılabileceği için bunu konuyu daha sonraki yazılarımdan birine erteleyip ApplicationContext’in farklı kullanım şekillerinden bahsediyorum.
- FileSystemXmlApplicationContext
Bu kullanımda ApplicationContext, bean tanımlarını bir xml dosyasından alır. XML dosyası tam dizini ile birlikte constructor’a verilir.
- ClassPathXmlApplicationContext
Bu kullanımda ise XML dosyasının tam dizinini vermeye gerek yoktur. XML dosyasının projenin classpath’inde olması yeterlidir.
- XmlWebApplicationContext
Bu kullanımda ise tüm beanler web uygulamasının içinde tanımlanır.
İnternette karşılaştığım diğer derslerde ApplicationContext tanımlarını anlatırken getBean() metodu ile beanlerin doğrudan xml konfigürasyonlarına göre elle oluşturulduğunu gördüm. Fakat bunun IoC’ye aykırı olduğunu düşündüğüm için öyle bir girişimde bulunmadım. Gözünüzün veya elinizin yanlış bir şeye alışmasındansa bu kısmın biraz daha soyut kalması daha doğru diye düşünüyorum. Tabii ki tercih ederseniz internette bu örnekleri bulabilirsiniz. Son olarak basit bir bean.xml dosyası göstereceğim.
Yukarıda örnek bir SelamVer class’ı var. Bu classı bean olarak konfigüre etmek istiyorum. Aşağıdaki xml dosyası bunu sağlıyor.
En üstteki dört satır xml, versiyonunu, web-app versiyonunu seçtiğimiz ve kullanacağımız namespace’leri eklediğimiz kısım. Buralar genellikle sabit olur. Aşağıdaki kısımda ise id yazan yerde bean’in adını, class kısmında SelamVer classının yerini verdik. Property kısmında ise örnek olarak selam değişkeninin değerini verdik.
Spring containerlar’la alakalı yazım bu kadar. Yazının başında da söylediğim gibi, anlattığım bu kavramların biraz soyut kalması gayet normal. En azından bir fikriniz olursa somut olarak bir şeyler yapmaya başladığınızda bu bilgilere ihtiyaç duyacaksınız.
Yararlandığım Kaynaklar:
- https://www.quora.com/Why-is-a-spring-container-known-as-an-IOC-container
- https://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/beans.html
- http://www.baeldung.com/inversion-control-and-dependency-injection-in-spring
- https://www.quora.com/What-is-IOC-Container-in-Spring
- https://adnjavainterview.blogspot.com/2018/01/what-is-ioc-container-in-spring.html