Spring – 03 – Inversion of Control (IoC) & Dependency Injection

Merhaba Arkadaslar.
Bu yazida Inversion of Control (IoC) & Dependency Injection kavramina ve turlerine goz atacagiz. Spring’te Dependency Injection’i gerceklestiren BeanFactory ve ApplicationContext arabirimlerinin farkina kisaca deginecegiz.

Inversion of Control & Dependency Injection

Inversion of Control (IoC) prensibi bagimlilarin(dependencies) olusturulmasi(creation) ve yonetimini(management) kod icerisinden kaldiran/developer’dan alan bir tekniktir.

Dependency Injection kavrami cogu zaman IoC kavrami yerine kullanilir. Dependency Injection aslinda IoC tekniginin bir alt kumesidir , yani bir IoC teknigidir.

Dependency Injection sadece Spring icin gecerli bir teknik degildir. Ornegin Java Server Faces ‘te (JSF) kullanilan @ManagedProperty annotation’ini kullanarak JSF ManagedBean’leri arasinda Dependency Injection teknigini kullanabiliriz. Boylelikle calisma zamaninda/runtime kendimiz, bagimli olan( dependency) ManagedBean objesini olusturmayiz @ManagedProperty annotation’ini kullanarak bu islemi JSF Implementation framework’une birakiriz.
Benzer sekilde CDI beanlerini kullandigimizda @Inject annotation’dan yararlaniriz.

IOC kavrami 2 alt kumeye ayrilir;

  • Dependency Lookup
    • Dependency Pull
    • Contextualized Dependency Lookup
  • Dependency Injection
    • Constructor Dependency Injection
    • Setter Dependency Injection

Dependency Lookup 

Dependency Lookup , daha geleneksel/traditional/eski bir yaklasimdir. Dependency Injection ise daha flexible/esnek ozellik gostermektedir.

Dependency Pull
Dependency Pull tekniginde bagimliliklar/dependencies gerektiginde registry’den cekilirler. Ozellikle EJB de Dependency Pull yaklasimi kullanilmaktadir.
Bununla birlikte Spring , dependency pull mekanizmasini destekler.Yonetilen/Manage component/object/objeleri dependency pull mekanizmasi ile alabiliriz /ulasabiliriz/retrieve.

Yaptigimiz Spring orneginde zaten Dependency Pull yaklasimini kullaniyoruz.

...
public class HelloSpringTest {
	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("01.appcontext.xml");		
		Car car = ctx.getBean("carId", Car.class); //dependency pull
		...
	}
}
...

Java Naming and Directory Interface

dependency pull

JNDI lookup ornegi icin ;

https://tomcat.apache.org/tomcat-8.0-doc/jndi-datasource-examples-howto.html

Context configuration

<Resource name="jdbc/myoracle" auth="Container"
              type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
              url="jdbc:oracle:thin:@127.0.0.1:1521:mysid"
              username="scott" password="tiger" maxTotal="20" maxIdle="10"
              maxWaitMillis="-1"/>

web.xml configuration

...
<resource-ref>
 <description>Oracle Datasource example</description>
 <res-ref-name>jdbc/myoracle</res-ref-name>
 <res-type>javax.sql.DataSource</res-type>
 <res-auth>Container</res-auth>
</resource-ref>
...

Code Example

Context initContext = new InitialContext();
Context envContext  = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/myoracle");
Connection conn = ds.getConnection();
//etc.

Contextualized Dependency Lookup
Contextualized Dependency Lookup (CDL), Dependency Pull ‘ a benzer. CDL de , lookup islemi registry’a degil container’a yapilir.

Contextualized Dependency Lookup

Injection vs Lookup

EJB 2.1 ya da onceki versiyonlari kullanildiginda bu durumda JNDI (Java Naming and Directory Interface ) ile lookup teknigi kullanilmalidir. Spring kullandigimizda bagimliklar/dependencies birbirine injection teknigi ile baglanacaktir.

Inversion of Control in Spring

Inversion of Control (IoC) , Spring Framework’unun en onemli ozelliklerinden biridir. Genel olarak Spring , Dependency Injection teknigini baz almaktadir.

Spring otomatik olarak uygulamamizdaki objeleri/bagimliliklari/dependencies baglamayacaktir. Bunun icin Spring’e ait konfigurasyonlari dogru sekidle yapmamiz gereklidir. Stand-alone Java uygulamalarinda main metodundan Spring IoC Container’i bootstrap/onyukleme edilmelidir.

Spring hem Dependency Injection Container’a hem de Dependency Lookup Container’a sahiptir.

Dependency Injection in Spring

Constructor Dependency Injection
Bagimliliklar/dependencies , yapilandirici/constructor kullanilarak inject edilir.

public class ConstructorInjection {
	private Dependency dependency;
	//dependency injection
	public ConstructorInjection(Dependency dependency) {
		this.dependency = dependency;
	}
}

Setter Dependency Injection
Bagimliliklar/dependencies , JavaBean-style setter methodlar uzerinden gerceklesir.

public class SetterInjection {
	private Dependency dependency;
	//setter injection
	public void setDependency(Dependency dependency) {
		this.dependency = dependency;
}

Spring , DI Container yapisi ile Setter,Constructor ve Method injection’i gerceklestirir. Dependency Injection’i gerceklestirebilmek icin BeanFactory ya da ApplicationContext arabirimini uygulayan(implements) siniflari kullanmamiz gereklidir.

dependency-injection

Setter injection yaklasiminda setter metotlar kullanilir ,
Constructor injection yaklasiminda constructor kullanilir.

Setter injection , Constructor Injection’a gore daha readable/okunabilirdir.

Setter injection yaklasiminda butun property’lerin inject edilmesi gerekmez , yani butun setter metotlari cagrilmayabilir.

Constructor injection kullandigimizda tum parametreler inject edilmelidir.

import org.springframework.beans.factory.annotation.Required;

public class Foo {

    private Bar bar;

    @Required
    public void setBar(Bar bar) {
        this.bar = bar;
    }
}

Beans & BeanFactories

DI Container tarafindan yonetilen componentlere “bean” adi verilir.
Dependency Injection Container’inda BeanFactory arabirimi core/temel kisminda yer almaktadir.BeanFactory component/objelerin, bagimliliklarin yonetiminden ve yasam dongusunden sorumludur.

Bu durumda BeanFactory arabirimini uygulayan (implements) bir sinif tipinde obje olusturulmalidir. BeanFactory implementation’i uzerinden bean’lere ulasim gerceklestirilebilir.

Car.java

package _02.beanfactory.impl.model;

public class Car {

	private String brand;

	public String getBrand() {
		return brand;
	}

	public void setBrand(String brand) {
		this.brand = brand;
	}
}

BeanFactoryImplTest.java

package _02.beanfactory.impl.test;

import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;

import _02.beanfactory.impl.model.Car;

public class BeanFactoryImplTest {

	public static void main(String[] args) {
		
                DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
		XmlBeanDefinitionReader rdr = new XmlBeanDefinitionReader(factory);
		rdr.loadBeanDefinitions(new ClassPathResource("02.appcontext.xml"));

		Car car = (Car) factory.getBean("carId");

		System.out.println(car.getBrand());
	}
}

02.appcontext.xml

<?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">

	<bean id="carId" class="_02.beanfactory.impl.model.Car">
		<property name="brand" value="ford"></property>
	</bean>
</beans>

Ornegimizi calistirdigimizda ;

ford

ApplicationContext

ApplicationContext arabirimi BeanFactory arabiriminin gelismis halidir. ApplicationContext ve BeanFactory arabirimleri getBean metodu ile Spring DI Container tarafindan yonetilen bean’lere erisim saglayacaktir.

ApplicationContext arabirimi HierarchicalBeanFactory arabirimini , HierarchicalBeanFactory arabirimi de BeanFactory arabirimini kalitmaktadir.(extends)

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
		MessageSource, ApplicationEventPublisher, ResourcePatternResolver { .... }
public interface HierarchicalBeanFactory extends BeanFactory { ...}

ApplicationContext arabiriminde DI hizmetine ek olarak , farkli hizmetleri de vardir.
Ornegin transaction, AOP , i18n (internationalization).

Buna ek olarak ApplicationContext arabirimi bean objesi olusturmak icin getBean metodunun cagrilmasini beklemez, Spring DI Container calistiginda bean objesini olusturur. BeanFactory ise getBean metodunun cagrilmasini bekler.

Spring tabanli uygulamalar gelistirdigimizde ApplicationContext arabiriminin kullanilmasi onerilir.

Configuring ApplicationContext
Spring , bean tanimlamalari XML dosyasi ya da property dosyasi ile yapilabilir. Spring 2.5 ile birlikte Java annotation ile de bean tanimi yapabiliyoruz.
XML ya da annotation tercihe gore kullanilabilir ya da bu 2 yaklasim birlikte kullanilabilir. Genelde uygulamanin alt yapisi (application infrastructure), ornegin data source , transaction manager gibi ayarlamalar/konfigurasyonlar XML dosyasinda yapilir , bunlar disindaki bean’ler annotation ile tanimlanir.

Basic Configuration Overview
XML konfigurasyonu icin Spring icin gerekli olan namepsace tanimini yapmamiz gereklidir. En temel olarak gerekli olan konfigurasyon su sekildedir;

<?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>

Spring farkli namespaceler de destekler. Ornegin AOP destegi icin aop , transactional destegi icin tx gibi.

<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">
   
</beans>

Github kaynak dosyalar/ source folder
leventerguder/injavawetrust-spring-tutorial

Yazimi burada sonlandiriyorum.
Herkese Bol Javali Gunler dilerim.
Be an oracle man , import java.*;
Levent Erguder
OCP, Java SE 6 Programmer
OCE, Java EE 6 Web Component Developer

Print Friendly, PDF & Email

Leave a Reply

Your email address will not be published. Required fields are marked *