Spring Framework Dersleri 2 - Inversion Of Control&Dependency Injection
Merhabalar. (Spring’e Giriş)[http://ilkaygunel.com/blog/2016/spring-giris/] yazımızın ardından bu yazımızda Inversion Of Control ve Dependency Injection konularını işleyeceğiz.
Inversion of Control Nedir?
Türkçe’ye kontol çevrimi olarak çevirilebilecek olan Inversion Of Control kontrol mekanizmasını developer’dan alarak kullanılan frameworkün mekanizmasına veren yapıdır.
Bizler kod yazarken nesneleri new’leyerek oluştururuz ve IoC mantığı da bunun developer’dan alınıp framework’e verilmesi yönündedir.
IoC konusu 2 alt alana ayrılır. Bunlar Dependency Lookup ve Dependency Injection‘dır.
Dependency Lookup da kendi içinde iki türe sahiptir.
- Dependency Pull: İlgili bağımlılığın gerekli olduğu zamanda çekilmesi işlemidir. Önceki yazıdaki örneğimizi hatırlayacak olursak XML’den ilgili bean’i çekme işlemi kod tetiklendiği anda yani ihtiyaç olduğunda gerçekleştirilecektir. Ayrıca Dependency Pull işleminde ilgili bean’ler, bağımlılıklar JNDI Registry’den okunurlar.
- Contextualized Dependency Pull: Çalışma mantığı olarak Dependency Pull’a benzerdir fakat bağımlılıklar Dependency Pull gibi bir registiry’den değil de container’den alınır.
Dependency Injection dediğimiz zaman da aklımıza iki yöntem geliyor:
- Constructor Based Dependency Injection: Bir sınıfın yapılandırıcısı vasıtası ile ilgili bağımlılığın karşılanması işlemidir. Aşağıdaki sınıfta da bağımlılık ihtiyacını yapılandırıcı vasıtası ile karşılayan sınıfı görmekteyiz.
package com.ilkaygunel.springtutorials;
public class ConstructorInjection {
private Dependency dependency;
public ConstructorInjection(Dependency dependency) {
this.dependency = dependency;
}
}
- Setter Based Dependency Injection: İlgili bağımlılığın bir set metodu vasıtası ile karşılanması işlemidir. Şu kod örneğimizdir:
package com.apress.prospring4.ch3;
public class SetterInjection {
private Dependency dependency;
public void setDependency(Dependency dependency) {
this.dependency = dependency;
}
}
Injection vs. Lookup
Eğer kodlamakta olduğunuz proje EJB’nin 2.1 ve öncesi sürümü içeriyorsa (ki bu saatten sonra hiç zannetmiyorum) IoC mekanizması Dependency Lookup olmaktadır. Spring Framework’te IoC mekanizması Dependency Injection ile çalışmaktadır.
Inversion of Control in Spring
IoC mekanizması Spring’in büyük parçalarından biridir. Spring’in çekirdeği Dependency Lookup’ı desteklemekle birlikte aslolan Dependency Injection üzerine inşa edilmiştir.
Spring Framework bağımlılık enjeksiyonunu otomatik, kendi başına yapacak şekilde konfigüre edilmemeiştir. Bir şekilde programcı tarafından bu bağımlılık enjeksiyonunun tetiklenmesi gerekmektedir. Önceki yazımızı tekrar göz önüne getirdiğimizde ClassPathXmlApplicationContext sınıfı vasıtası ile bağımlılık enjeksiyonunu sağlamıştık.
Dependency Injection in Spring
Spring framework içinde DI (bağımlılık enjeksiyonu) için iki mekanizma mevcut. Bunlar BeanFactory ve ApplicationContext’tir.
Beans & BeanFactories
Spring içerisinde container tarafından yönetilen tüm elemanlara bean ismi verilir. Örneğin bir sınıf içinde Spring vasıtası ile sağladığımız bir bağımlılık bizim için bean olmuş olur.
BeanFactory Interface ise Spring’in DI container’ının çekirdeğidir. BeanFactory componenet’lerin yönetiminden ve içerdiği bağımlılıklarla birlikte yaşam döngüsünden sorumludur.
Önceki yazıdaki HelloWorldDI sınıfımızı şu şekilde güncellersek BeanFactory kullanmış oluruz:
package com.ilkaygunel.springtutorials.helloworld;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;
public class HelloWorldBeanFactory {
public static void main(String[] args) {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader rdr = new XmlBeanDefinitionReader(factory);
rdr.loadBeanDefinitions(new ClassPathResource("beans.xml"));
MessageRendererImplementation renderer = (MessageRendererImplementation) factory.getBean("renderer");
renderer.render();
}
}
ApplicationConetxt
ApplicationContext arabirimi BeanFactory arabiriminin genişletilmiş halidir. ApplicationContext arabirimi sadece DI işlemleri için değil, transaction, AOP, internalization, event handling gibi mekanizmalar da sunar.
Spring’in kendisi de uygulama geliştirirken ApplicationConetxt’den faydalanılmasını tavsiye ediyor.
BeanFactory ile çalıştığımızda getBean metodu çağırılmadan önce bean objesi oluşturulmaz yani metodun çağırılmasını bekler. Fakat ApplicationContext bu beklemeyi yapmaz ve DI Container çalıştığı andan itibaren obje oluşturulur.
Önceki yazıda kullandığımız ClassPathXmlApplicationContext sınıfı da ApplicationContext’dan türetilmiş bir sınıftır.
Configuring ApplicationContext
Spring içerisinde bean tanımlamaları benim gördüğüm kadarı ile ya XML ya annotation ya da ikisi beraber kullanılarak yapılabiliyor. Burada neyi ne zaman kullanacağınız uygulamanızın mimarisine, proje geliştirme kurallarınıza göre vs. değişebilir.
Basic Configuration Overview
En temel konfigürasyonda XML dosyası içinde namespace alanı dediğimiz 2. satırdan itibaren başlayıp bir takım tanımlamaların yapıldığı kısımda uygulamamız için gerekli namespace’lerin eklenmesini Spring şart koşar. En temel hali ile içi boş bir konfigürasyon şu şekilde olur:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
İleriki derslerimizde notasyonlar da kullanacağız ve konfigürasyona bu anotasyon desteğini eklememiz gerekir. Onu da
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="package-name" />
</beans>
Bu yazımızda bu kadar arkadaşlar. IoC, DI, BeanFactory ve ApplicationContext konularını işlemiş olduk. Gelecek yazıda görüşene kadar sağlıcakla kalın.
Selam ve Sevgilerimle
NOT: Yazıda Spring Pro 4 ve http://www.injavawetrust.com/spring-03-inversion-of-control-ioc-dependency-injection/ kaynakları kullanılmıştır.