Spring Framework Dersleri 1 - Spring'e Giriş ve Hello World
Merhabalar.
Bu yazı ile ne zamandır niyetli olduğum, hem unuttuklarımı öğrenmek hem de paylaşım yapma amaçlı olduğum Spring Framework yazılarına bu yazı ile başlıyorum. Allah bana en azından yazı dizisini bitiremesem bile bolca içerik üretebilmeyi nasip etsin.
Yazı Dizisi Boyunca Hangi Kaynakları Kullanacağız?
Spring Framework yazı dizisi boyunca
- Özcan Acar hocamızın Spring kitabı
- apress.com’dan satın alabileceğiniz Pro Spring 4 kitabı
- internetteki çeşitli kaynaklar
bizim referans kaynaklarımız olacak.
Daha önceki yazı dizilerimde yakışıksız bir şekilde hırsızlık vb. ithamlarla karşılaştığım için söylemem gerekir ki anlatımlarım kitaplardan kopyala yapıştır şeklinde olmamaktadır. Kendi anladığım ne ise onu anlatmaktayım.
Spring Framework Nedir?
En basit tabiri ile Spring Framework Java uygulamalarını daha hızlı ve pratik şekilde geliştirilmesi, geliştiricilerin işlerini kolaylaştırılması amacı ile ortaya çıkarılmış bir framework’tür.
Çokça meşhur olan, ülkemiz yazılım piyasasında da oldukça popüler olan Spring Framework’ün geçmişi ve ortaya çıkışı Java EE’nin ilk zamanlarındaki kullanım zorluğuna dayanıyor. Spring’in çıktığı sıralarda Java EE spectlerini uygulamak, kullanmak çok zordu. Spring’in geliştiricileri adeta krizi fırsata çevirdiler ve Java EE’ye göre çok daha kolay kullanılabilen, uygulanabilen bir framework ortaya çıkardılar. Tabii ki yazılım geliştiricileri kolayı varken zoru seçmediler ve Spring framework tabir yerinde ise aldı yürüdü.
İlk çıktığı zamanlarda belli başlı sorunlara, bağımlık enjeksiyonu gibi, çözüm getiren bir framework olan Spring bugün artık çok büyük bir aile. Çatısı altında çok sayıda kütüphane yer almakta. En bilinenleri Spring MVC, Spring Security, Spring Data gibi kütüphanelerdir. Bu kütüphanelerin tamamı Spring geliştiricileri tarafından modüler olarak tasarlanmıştır. Yani birbirlerinden bağımsızdırlardır ve projenizde ihtiyacınız olanı kullanabilirsiniz.
Yeri geldikçe yeni açıklamalar ve tanımlamalar yapacağız.
İlk Uygulama –> Hello World
Adet olduğu üzere yeni bir dil, framework vs. öğrenilirken Hello World ile başlarız. Şimdi biz de bir Hello World uygulaması yapacağız.
Şimdi siz kendi IDE’niz içerisinde bir Maven Java projesi açın. Ben dersleri Eclipse IDE üzerinde yürüteceğim ve zaman zaman da Spring Tool Suite ile de çalışacağız.
Standart bir Java projesinde Hello World’ü basitçe şöyle yapıyorduk:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
Peki işi biraz zorlaştırırsak? İşin içine Interface’ler falan girerse? Büyük projelerde bir çok Interface ve onları uygulayan sınıflar kol gezer. Biz de basitçe hemen örnekleyelim…
İçerisinde sadece mesaj döndürmekle yükümlü bir metot tanımlanmış olan MessageProvider interface’miz şöyle olsun:
public interface MessageProvider {
String getMessage();
}
Mesajın ekrana yazdırılması için yazdırma, MessageProvider interface’ini implement eden sınıf nesnesini set ve get eden metotların barındığı interface’miz de şöyle olsun.
public interface MessageRenderer {
void render();
void setMessageProvider(MessageProvider provider);
MessageProvider getMessageProvider();
}
Bu interface’lerin ardından şimdi implementasyonlarına bakalım.
Bize bir mesaj döndürecek olan metodu barındıran MessageProvider interface’ni uygulayan MessageProviderImplementation sınıfımız mesaj olarak Hello Spring World :)” String’ini bize döndürecek.
package com.ilkaygunel.springtutorials.helloworld;
public class MessageProviderImplementation implements MessageProvider{
public String getMessage() {
return "Hello Spring World :)";
}
}
Mesajın ekrana yazdırılması için gerekli metotların tanımlarını içinde barındıran MessageRenderer interface’ini uygulayan MessageRendererImplementation sınıfımız ekrana yazdırma işlemini yapan render() metodunu ve MessageProvider’ı uygulayan sınıftan bir nesnenin get-set metotlarının uygulanmış halini barındırıyor.
package com.ilkaygunel.springtutorials.helloworld;
public class MessageRendererImplementation implements MessageRenderer {
private MessageProvider messageProvider;
public void render() {
if (messageProvider == null) {
throw new RuntimeException(
"MessageProvider Interface'ini Uygulamış Bir Sınıfın Nesnesini Göndermelisiniz:"
+ MessageRendererImplementation.class.getName());
}
System.out.println(messageProvider.getMessage());
}
public void setMessageProvider(MessageProvider provider) {
this.messageProvider = provider;
}
public MessageProvider getMessageProvider() {
return messageProvider;
}
}
Interface’lerimizi yazdık, sınıflara uygulattık. Şimdi sadece kullanması kaldı. HelloWorld sınıfımız içerisinde bunları kullanalım.
package com.ilkaygunel.springtutorials.helloworld;
public class HelloWorld {
public static void main(String[] args) {
MessageProvider ms = new MessageProviderImplementation();
MessageRenderer mr = new MessageRendererImplementation();
mr.setMessageProvider(ms);
mr.render();
}
}
Bu uygulamayı çalıştırdığımızda konsolda Hello Spring World :) çıktısını alacağız. Peki şimdi bu uygulamayı yaptık da ne oldu?
Gelmek istediğim nokta şu ki biz Hello World sınıfını 2 adet sınıfa bağımlı hale getirdik. Yazılım dünyasında sınıflar arasında ne kadar az bağımlılık olursa yazım o kadar kullanışlı ve bakıma uygun olur. Bu nedenle Loose coupling (Zayıf Bağımlılık) denen olay yazılım geliştirilirken hedeflenen olgulardan birisidir. Spring Framework de bu ihtiyacı pratik ve kolay bir şekilde karşılayabildiğinden popülerleşmesi hızlı olmuştur.
Şimdi bu uyglamayı Spring Framework kullanarak nasıl daha az bağımlı hale getirebiliriz ona bakalım.
Öncelikle projemizdeki pom.xml dosyamıza şu bağımlılığı ekleyelim:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.3.RELEASE</version>
</dependency>
Akabinde src/main/resources/ dizini altında beans.xml adında bir dosya oluşturalım ve içeriğini şöyle düzenleyelim:
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="provider" class="com.ilkaygunel.springtutorials.helloworld.MessageProviderImplementation" />
<bean id="renderer" class="com.ilkaygunel.springtutorials.helloworld.MessageRendererImplementation"
p:messageProvider-ref="provider" />
</beans>
Spring’de bağımlılık ihtiyacı iki yolla sağlanabilir ve XML ile bu ihtiyacı sağlamak bu yollardan birisidir. Diğer yola ilerleyen derslerde değineceğiz.
Şimdi bu XML dosyasını inceleyelim. İlk 2-6 satırları arasında Spring’in XML tag’lerine ait tanımlamalar yer alıyor. 7. satırda bizim MessageProvider interface’mizi uygulayan MessageProviderImplementation sınıfı privovider id bilgisi ile Spring’e kayıt ettiriliyor. 8. satırda ise bizim MessageRenderer interface’mizi uygulayan MessageRendererImplementation sınıfımız renderer id bilgisi ile kayıt ettiriliyor yalnız MessageRendererImplementation’ın kayıt edilmesi sırasında fazladan bir şey daha var: p:messageProvider-ref=”provider”
p:messageProvider-ref=”provider” ifadesi ile biz Spring’e diyoruz ki, MessageRendererImplementation sınıfı içerisinde messageProvider adında bir alan var ve sen bu alanı bu XML içindeki provider id bilgili sınıftan bir nesne oluşturup otomatik olarak doldur. Böylece biz main metodumuz içinde MessageProviderImplementation nesnesi oluşturmaktan kurtulmuş oluyoruz ve sınıfımızın bağımlılığı bir nebze azalmış oluyor.
Şimdi HelloWorld sınıfımızın güncellenmiş haline bakalım:
package com.ilkaygunel.springtutorials.helloworld;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloWorldWithDI {
public static void main(String[] args) {
try (ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(
"beans.xml")) {
MessageRenderer mr = classPathXmlApplicationContext.getBean("renderer",
MessageRendererImplementation.class);
mr.render();
} catch (Exception e) {
System.err.println("Bir Hata Meydana Geldi! Hata:" + e);
}
}
}
HelloWorldWithDI sınıfımız içerisinde try’ın hemen başında ClassPathXmlApplicationContext sınıfından bir nesne oluşturuyoruz ve ClassPathXmlApplicationContext sınıfının yapılandırıcısına beans.xml’i parametre olarak gönderiyoruz.
try bloğunun içinde ise MessageRenderer interface’i tipinde bir nesne tanımlıyoruz ve bu nesnenin içinin doldurulması işlemini az önce tanımladığımız ClassPathXmlApplicationContext tipindeki nesne ile yapıyoruz.
ClassPathXmlApplicationContext tipindeki classPathXmlApplicationContext nesnesi beans.xml içindeki bean’leri okuyabilir ve kullanabilir. Burada da biz getBean() metodunu kullanarak XML içinde tanımlanmış bean’lere ulaşabiliriz. Bizim burada beans.xml’den sadece MessageRendererImplementation sınıfını çekmemiz yeterli olacaktır çünkü az önce de belirttiğim gibi MessageRendererImplementation sınıfı içindeki alan otomatik olarak dolacaktır. MessageProviderImplementation sınıfına ait çekim yapıp uğraşmaya gerek yoktur. getBean() metodunu kullanırken parametrelerden birincisi XML içinde tanımlı bean id’si, ikincisi ise hangi sınıf türünde bean çekileceğidir. renderer id’li olan ve MessageRendererImplementation sınıfı tipinde bean’i çekeceğiz. Akabinde de son oalrak MessageRendererImplementation sınıfından render() metodunu çağırarak yazdırma işlemini yapacağız.
Ekran Çıktısı
HelloWorldWithDI sınıfına sağ tıklayıp Rus As -> Java Application dediğimizde şu ekran çıktısını alabiliriz.
Gördüğünüz gibi aynı işlem Spring Framework ile yapıldı ve bağımlılık azaltımı konusunda yol alındı.
Bu ilk yazımızda Spring’e bir giriş yaptık ve Hello World örneğimizi uyguladık. Gelecek yazıda Inversion Of Control ve Dependency Injection konularını işleyeceğiz.
Sağlıcakla Kalın
Selam ve Sevgilerimle