Spring Derlemesi
Bean’leri bir önceki yazıda detaylı şekilde inceledikten sonra; Spring’in başka kolaylıklarına bakalım.
@SpringBootApplication uygulamanızın başlangıç noktası olarak işaretleyen anatosyondur. Bu anotasyon Spring Boot projesi için mecburi değildir, ancak bazı işlevsellikleri kolaylaştırdığı için genellikle kullanmayı tercih ediyoruz.
@SpringBootApplication birkaç açıklamanın birleşimidir;
- @EnableAutoConfiguration: Uygulamanın başlatılması sırasında otomatik yapılandırmayı etkinleştirmek için kullanılır. Bu anotasyon sayesinde Spring Boot, uygulamanız için gerekli olan yapılandırmaları otomatik olarak yükler ve çalıştırır.
- @SpringBootConfiguration: Class seviyesine kullanılır, ve @Configuration anotasyonuna benzer.
- @ComponentScan: Belirtilen paketteki (ve alt paketlerdeki) bileşenleri (@Component, @Service, @Repository gibi) otomatik olarak tarar ve bağlar. @ComponentScan, Spring’in bileşenleri tarayacağı paketi belirtmek için @Configuration anotasyonu ile birlikte kullanılır. @ComponentScan anotasyonu ayrıca sınıflar için bean’leri scan, detect ve register eder. @ComponentScan anotasyonu değer alabilir, ama argümansız olarak kullanılırsa; Spring’ e geçerli paketi ve tüm alt paketlerini taramasını söyler.
@SpringBootApplication zorunlu olmamakla birlikte Spring Boot projelerinde işleri kolaylaştıran bir yapıdır. Kullanmamanız durumunda yukarıdaki anotasyonları manuel olarak eklemeniz gerekir.
Anotasyonlar, Spring’ de dependency injection işlemini kolaylaştırır. XML konfigürasyon dosyalarını kullanmak yerine, bean’ leri tanımlamak için sınıflar ve metotlar üzerinde Spring Bean anotasyonunu kullanabiliriz.
IoC(Inversion of Control) konteyneri: Spring IoC konteyneri bean’leri yapılandırır ve yönetir. IoC Konteyneri (diğer adıyla DI Konteyneri), otomatik dependency injection uygulamak için kullanır. Nesne oluşturmayı ve yaşam süresini yönetir ve ayrıca sınıfa bağımlılıklar enjekte eder. IoC konteyneri belirtilen sınıftan bir nesne oluşturur ve tüm bağımlılık nesnelerini çalışma zamanında bir yöntem aracılığıyla enjekte eder ve uygun zamanda siler. Bu durumda biz, nesneleri manuel olarak oluşturmamış ve yönetmemiş oluyoruz. ( Teşekkürler Spring )
ApplicationContext: Spring IoC konteyneri, nesnelerin tüm yaşam döngüsünü örneklemek(instantiating), wiring, yapılandırmak(configuring), ve yönetmekten(managing) sorumludur. BeanFactory ve ApplicationContext, Spring IoC Konteynerlerini temsil eder. ApplicationContext, BeanFactory’nin alt arayüzüdür. Bu iki konteyner, Spring bean’ lerini yönetir ve enjekte eder, ancak bunu yaparken farklı yaklaşımlar kullanırlar.
BeanFactory:
- Gecikmeli Yükleme (Lazy Initialization): BeanFactory, yalnızca ihtiyaç duyulduğunda (bean gerçekten çağrıldığında veya kullanıldığında) bean’leri yükler ve oluşturur. Bu, belleği daha verimli kullanmaya yardımcı olabilir ve başlangıçta daha az kaynak tüketir.
- Minimal Functionality: BeanFactory, temel IoC özelliklerini sağlar ve temel bağımlılık yönetimi yapar. Genellikle hafif uygulamalar ve kaynak kullanımı önemli olan durumlar için tercih edilir.
- Explicit Configuration: BeanFactory genellikle daha basit ve daha az özellik içerir. Bu nedenle, daha az soyutlama katmanı ve dolayısıyla daha az ek işlevsellik sunar.
Lazy Initialization: Bean sadece çağrıldığında oluşturulur.
Eager Initialization: Bean uygulama başlatılırken oluşturulur.
ApplicationContext:
- Hızlı Yükleme(Eager Initialization): ApplicationContext, uygulama başlatıldığında tüm bean’leri yükler ve oluşturur. Bu, başlangıçta daha fazla kaynak kullanımı gerektirebilir, ancak uygulamanın daha sonra hızlı ve tutarlı bir şekilde çalışmasını sağlar.
- Enhanced Functionality: ApplicationContext, BeanFactory’nin tüm işlevlerini içerir ve ek özellikler sunar. Örneğin, event yayınlama ve dinleme, mesajlaşma desteği, AOP (Aspect-Oriented Programming) entegrasyonu, uluslararasılaştırma (internationalization) desteği gibi.
- Convenience: ApplicationContext ile çalışmak genellikle daha kolaydır, çünkü daha fazla yapılandırma ve yönetim aracı sağlar. Özellikle karmaşık ve büyük ölçekli uygulamalarda tercih edilir.
Büyük ve karmaşık uygulamalar için ApplicationContext tercih edilirken, daha hafif, basit veya yalnızca bellek tüketimi kritik olduğu durumlar için BeanFactory kullanımını tercih edebilir.
Dependency injection: Dependency Injection (DI), yalnızca Spring Framework’ e özgü bir kavram değildir. Bu, genel olarak Nesne Yönelimli Programlama’ da (OOP) kullanılan bir tasarım deseni ve yazılım geliştirme tekniğidir. (örneğin, SOLID ilkelerinden “Dependency Inversion Principle”) Amaç, bir sınıfın ihtiyaç duyduğu bağımlılıkları başka bir yerden almasını sağlamaktır. Yani, sınıf bağımlılıklarını kendisi oluşturmaz.
DI’ nin amacı, bağımlılıkların oluşturulmasını, bunlara ihtiyaç duyan sınıftan ayırmaktır. Bu yaklaşım, sınıflar arasındaki bağımlılıkların gevşek bağlı olmasını sağlar, böylece kod daha modüler, test edilebilir ve bakım yapılabilir hale gelir. DI genellikle bir IoC konteyneri tarafından yönetilir ve Spring Framework bu prensibi çok etkili bir şekilde uygular.
DI aslında IoC’ nın implement edilmesini sağlayan bir pattern’dir. Programımızın ihtiyacı olan bağımlılıkları sağlar. Kısacası ihtiyacımız olan beanı Spring bize getirir ve sınıf içerisinde inject eder. Spring ile bunu yapmanın 3 yolu vardır.
- Constructor ile DI
- Setter ile DI
- Field ile DI
“Spring dokümantasyonu, zorunlu bağımlılıklar için constructor tabanlı enjeksiyonun kullanılmasını öneriyor.”
Constructor injection: Bu, nesnenin oluşturucusunun bağımlılıkları enjekte etmek için kullanıldığı bir Spring Bağımlılık Enjeksiyonu türüdür. Eğer constructor çağrılmazsa nesne oluşturulamaz ve bu durum; bu enjeksiyon türünü daha güvenli yapar.
Setter injection: Spring framework’ünün bağımlılık nesnesini setter metodunu kullanarak enjekte ettiği yöntemdir.
Field DI: Sınıfın alanlarına doğrudan bağımlılıkları enjekte etme yöntemidir. Bu yöntem, @Autowired gibi anotasyonlar kullanarak bağımlılıkları doğrudan sınıf alanlarına enjekte eder.
Field DI; ilk bakışta daha basit ve temiz görülebilir, ancak bu yöntem, bağımlılıkları enjekte etmek için reflection kullanır. Reflection, constructor veya setter bazlı enjeksiyondan daha yavaştır, çünkü runtime’ da ek yük getirir yani daha maliyetlidir.
“Bazı durumlarda constructor injection ihtiyacı karşılamaya yetmez.
Class Lib “A” < — — → Class Lib “B”
Yukarıda gösterildiği circular dependency durumu oluşursa, yani iki obje birbirine dependent olması durumu gibi, ve bu circle içindeki sınıfların tamamı constructor injection kullanır ise bu durumda beanler yaratmayacağı için Spring exception fırlatır. Bu hata ile baş etmenin tek yolu bu durumdaki en az bir sınıfın constructor injection yerine field yada setter injection yöntemi tercih etmesi gerekir. Setter injection ile Spring, bean’ leri ilk önce oluşturup, bağımlılıkları daha sonra set eder, bu da circular dependency’ nin oluşmasını engeller.“
Spring Hangi Tasarım Desenlerini Kullanıyor?
- Singleton: Varsayılan olarak Spring, tüm Bean’leri Singleton olarak tanımlar ve her Bean için sadece bir örnek oluşturur. @Scope anotasyonu ile bu davranış özelleştirilebilir.
- Factory Method: Bu pattern nesne oluşturma sürecini soyutlamak için kullanılır. BeanFactory ve ApplicationContext bu pattern üzerine inşa edilmiştir. Spring’in IoC konteyneri, Bean tanımlarına dayanarak nesneleri dinamik olarak oluşturur.
- Proxy: Spring Framework’ ün en sık kullandığı tasarım desenlerinden biridir. Dinamik olarak bir nesnenin yerine geçen proxy nesneleri kullanarak ek işlevsellik sağlar (örneğin, güvenlik, performans ölçümü). Spring AOP (Aspect-Oriented Programming) proxy desenini kullanır.
- Prototype: ApplicationContext herhangi bir bean tanımından her getBean(‘beanName’) ile erişimde yeni bir instance yaratmaktadır. Bean tanımı burada prototype yaklaşımı sağlar.
- Template Method: Aynı işlemlerin ortak kısımlarını soyutlayarak alt sınıfların özelleştirilmiş davranışları tanımlamasına olanak tanır. JdbcTemplate, HibernateTemplate, JpaTemplate, RestTemplate.
- Observer: Bir nesnedeki değişikliklerin, bu nesneye bağımlı diğer nesnelere bildirilmesini sağlar. Spring’ in event mekanizması ApplicationEvent ve ApplicationListener bu deseni uygular.
- Front Controller: Tüm istekleri merkezi bir denetleyici aracılığıyla yönlendirmek için kullanılır. Spring MVC’ deki DispatcherServlet bu deseni uygular.
- Command Pattern: Bir işlemi nesne olarak sarmalayarak, işlem üzerinde kontrol sağlar. Spring Batch, her adımı bağımsız bir işlem olarak uygulamak için bu deseni kullanır.
Spring Framework, yazılım geliştirme sürecini kolaylaştıran güçlü özelliklere ve prensiplere sahiptir. Bu yazıda Spring’in temel yapı taşlarından bahsettik ve sık kullanılan tasarım desenlerini ele aldık.
Başka bir yazıda görüşürüz! 🙂