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
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.
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.
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
Leave a Reply