Bu yazıda en basit şekilde anotasyonların çalışma mantığı yer almaktadır. Ayrıca kısa ve öz bir şekilde, en çok kullanılan anotasyonlara, çalışma mantıklarına ve benzer anotasyonarla aralarındaki farklara değindim. Daha fazla bilgi edinilebilmesi adına yazı sonuna kaynakça listesi ekledim. Konuyla ilgili yorum ve görüşlerinizi yanın en altındaki yorum formu üzerinden iletebilirsiniz.
Spring MVC Framework / Spring Boot Anotasyonları (Annotations) Nedir?
Annotation kelimesinin Türkçe karşılığını, kimi yerlerde "notasyon" kimi yerlerde ise "anotasyon" ifadesini görebilirsiniz. Peki kısaca nedir bu Annotations denilen kavram.- Developlement anında IDE veya compiler tarafından yada run-time anında framework tarafından yorumlanan ifadelerdir.
- Bir öğenin tanımını yapar, ne yapması gerektiğini açıklar ve yazılım geliştirme sürecini hem hızlandırır hem de kolaylaştırır.
- Anotasyonlar kodun içerisinde tanımlandıktan sonra, işlevsel hale gelebilmeleri için Spring tarafından 2 defa taranırlar.
- İlk önce yalnızca anotasyonları (spring tarafından yönetilen bean) taranır ve yapılmas gereken görev eşleştirmeleri yapılır.
- İkinci taramada ise anotasyon tanımlamasına göre işlemini yapar.
- Tüm Spring Bean’leri “App Context” yada "Spring Context" (IoC container) adı verilen bir container içinde yaşarlar.
Anotasyonlar çok güçlü kullanımlardır ve çok farklı şekillerde kullanılabilirler. Birkaç örnek vermek gerekirse:
- Kısıtlamaları ve kullanımı tanımlayan anotasyonlar: @Deprecated, @Override, @NotNull
- Bir öğenin çalışma yapısını belirten notasyonlar: @Entity, @TestCase, @WebService
- Bir öğenin davranışını belirten notasyonlar: @Statefull, @Transaction
- Bir öğenin nasıl işleneceğinin belirten notasyonlar: @Column, @XmlElement
Özetle, her durumda bir öğeyi tanımlamak ve anlamını netleştirmek için kullanılan notasyon türleri vardır. Burada öğe olarak bahsedilen şey bir değişken olabilir, bir fonksiyon veya bir sınıf olabilir.
Temel Spring Boot Anotasyonları
- @Bean - Bir metodun Spring tarafından yönetilen bir Bean ürettiğini belirtir
- @Service - Belirtilen sınıfın bir servis sınıfı olduğunu belirtir.
- @Repository - Veritabanı işlemlerini gerçekleştirme yeteneği olan yapıldığı repository sınıfını belirtir.
- @Configuration - Bean tanımlamaları gibi tanımlamalar için bir Bean sınıfı olduğunu belirtir
- @Controller - Requestleri yakalayabilme yeteneği olan bir web controller sınıfını belirtir.
- @RequestMapping - controller sınıfının handle ettiği HTTP Requestlerin path eşleştirmesini yapar
- @Autowired - Constructor, Değişken yada setter metodlar için dependency injection işlemi gerçekleştirir
- @SpringBootApplication - Spring Boot autoconfiguration ve component taramasını aktif eder.
@Autowired Anotasyonu Nedir? Çalışma Mantığı Nedir?
Spring Contex, container enjeksiyon noktalarını bularak, orada bir nesne oluştrur. New anahtar kelimesi ile bir nesne oluşturulmaz. Kullanılacak nesne Spring tarafından oluşturulur. Bu sayede, dependency injection tasarım kalıbı (design pattern) da uygulanmış olur.Özetle @Autowired yalnızca injection için
kullanılır. @Autowired ifadesini kullanabilmek için, her iki sınıf da Bean sınıfı olmalı. Örneğin @Service anotasyonu ile tanımlanmış bir servis sınıfı, @Repository ile tanımlanmış bir sınıftan @Autowired ile bir nesne üreterek, veritabanı işlemlerini gerçekleştirebiliyor. Burada @Servie ve @Repository tanımlarının yapıldığı sınıflar için Spring IoC Container (application context) içerisinde gerekli Bean'ler oluşturulduğu için, her iki sınıf da aslında Bean sınıfı olmuş oluyor. Dolayısıyla service sınıfı içerisinde repository sınıfı için @Autowired işlemi yapılabiliyor.
Kısaca @Autowired, bean nesnesinin istenilen alana, başka bir bean nesnesinin alınıp, yerleştirilmesiyle olur.
Anotasyon Kullanmadan IoC Container İçinde Nasıl Bean Oluşturulur?
Anotayonlar aracılığıyla otomatik olarak Spring IoC Container içinde oluşturulup, işlerimizi kolaylaştıran işlemlerin tanımlamasını, XML dosyası içinde de yapılabiliriz. Yine anotasyon kullanmış gibi, Spring IoC Container içinde işlerimizi kolaylaştıran otomatik Bean'ler tanımlanmış olacaktır. Anotasyon ile tanımlama yapmak, daha yeni bir kullanımdır. Biz anotasyon kullandığımız zaman aslında arkaplanda, yazdığımız anotasyonun XML tanımlaması otomatik yapılarak, application context (Spring IoC Container) içine gerekli kayıt işlemleri yapılıyor.
// @Autowired edilen sınıf.
class EnglishGreeting {
@Autowired
private Greeting greeting;
}
// xml dosyasında gerçekleşen olay.
<bean id="englishGreeting" class="com.bean.EnglishGreeting"></bean>
id = sınıf adı
class = sınıfın konumu
// @Autowired ile tanımlamak yerine, XML olarak şöyle tanımlanabilir.
<bean id="englishGreeting" class="com.bean.EnglishGreeting">
<property name="greeting" ref="greeting"/>
</bean>
@Qualifier Nedir? Ne Zaman Kullanılır?
Eğer bir interface birden fazla sınıf tarafından implement
edildiyse, bu sınıflardan hangsine ait fonksiyonun kullanılacağını bilmek
için, @Autowired tanımlamasına ek olarak @Qualifier(“SınıfAdı”) adında bir annotation
daha eklendiği takdirde, yine New ile o sınıftan özel bir nesne
türetmeye gerek kalmadan, o sınıfın fonksiyonunu (gerekliyse parametre göndererek) kullanabiliyoruz.
Örnek :
@Component("posts") public class Posts implements Blogafem{ public String print() { return "post"; } } @Component("comments") public class Comments implements Blogkafem{ public String print() { return "comment"; } }
@Service public class BlogkafemService{ @Autowired @Qualifier("posts") private
Blogkafem blogkafem
; }
Bu örnekte, Blogkafem adlı Interface implementasyonu iki sınıf tarafından yapılmış. @Autowired anotasyonu ile injection işlemi yapmak istersek, Spring bu sınıflardan hangisini enjekte edeceğini bilemez ve kod hata verir. Bu sebeple, @Qualifier belirteci ile hangi sınıfı enjekte edip kullanacağımızı seçmiş oluyoruz. Şayet, iki sınıf değil de tek sınıf olsaydı ve sınıflar arası bir seçim yapmak zorunda kalmamış olsaydık, o zaman @Autowired kullanımı tek başına yeterli olacaktı.
@Component Anotasyonu Nedir? Nasıl Çalışır?
- Bir sınıfı “Bean” olarak işaretler. (spring tarafından yönetilen bean)
- Bu sayede Spring’in component tarayıcısı bu sınıfı alıp “App Context” içine ekler.
- Genel amaçlı kullanımlar içindir.
- @Component ile context:component-scan projedeki tüm @Component ifadelerini tarar.
- @Component tanımı aslında XML dosyası içindeki şu tanımlamaya eşittir
.
<bean id="sinifAdi" class="com.bean.sinifAdi
"></bean>
- Class seviyesinde bir anotasyondur.
- Component taraması sırasında bu anotasyona ait sınıflar taranır.
- @Repository, @Service, @Configuration ve @Controller anotasyonlarının tamamı @Component anotasyonudur.
- https://www.baeldung.com/spring-bean-annotations
- https://codeboje.de/difference-spring-bean-component/
@Service Anotasyonu Nedir? @Component Anotasyonundan Farkı Nedir?
@Service, projenin bussines logic kısmında kullanılır ve tanımlandığı sınıfı “Bean” sınıf haline getirir. @Service anotasyonu yerine aynı işlemi yapan ve temel annotation olan @Component de kullanılabilir fakat, @Service anotasyonu amacımıza yönelik daha fazla şey sunuyor. Yani @Component tanımlamasının aynısı ama bir üst modelidir denilebilir. Ayrıca @Service anotasyonunun kullanımı, tanımlandığı sınıfın bir servis sınıfı olduğunu belirtip, anlaşılırlığı arttırması açısından da daha uygundur. Bu sayede artık, Controller tarafından yakalanan istekler ile veritabanı sorgularını gerçekleştiren Repository sınıfı arasında köprü görevi görerek, son kullanıcıya gerekli cevabı üretecek bir sınıf olduğu anlaşılır. Bu aynı zamanda kod bütünlüğünü de sağlar. Projeye sonradan dahil olacak kişi, Service sınıfının hangisi olduğunu ve Controller aracılığıyla kullanıcıdan gelen isteklerin nerede işlemesi gerektiğini bilir.@Component Bazlı Anotasyonlar Hangileridir? @Component ile Arasındaki Farklar Nelerdir?
@Component bazlı anotasyonları özetle şu şekilde ifade edebiliriz.
- @Service, @Controller, @Repository, @Configuration = {@Component + ek işlevsel özellikler}
Yani başka bir deyişle, @Service, @Repository, @Controller, @Configuration tanımları, daha özel kullanımlar için @Component tanımlamasının özelleşmiş halleridir. En basit örneği özelleşmiş exception çıktıları almak. Bu tür özel tanımlamaları amacına uygun yerlerde kullanarak, daha özel exception çıktıları alınabilir. Örneğin, @Repository kullanımı, kullanıldığı sınıfta herhangi bir istisna durum oluşursa, hata olarak veritabanına özel exceptionlar dönecektir.
Kısaca Component, Repository, Service, Controller Anotasyonları
- @Component : auto-scan için genel bir ifade. Spring tarafından yönetilen Bean'leri tarar ve IoC Container içine ekler.
- @Repository : veritabanı işlemleri gerçekleştiren sınıflarda kullanılır.
- @Service : yazılımın bussines logic kısmını gerçekleştiren sınıflar için kullanılır.
- @Controller : frontend veya api isteklerinin karşılayan sınıfları tanımlamak için kullanılır.
Ortak özellikleri: Bean tanımlaması için, tarama/otomatik algılama ve dependency injection yapmak.
@Repository
- Veritabanı sorgularının gerçekleştirildiği sınıfları belirten bir anotasyondur.
- Database kaynaklı exception yakalar. (Platform specific exceptions)
- Anotasyon tanımından sonra, ilgili sınıf için otomatik olarak XML dosyasında bean tanımlaması eklenir.
- Spring JPA veya JPA alternatifi database işlemlerini gerçekleştiren yapılar @Repository tanımlamasına sahip sınıflar üzerinden kullanılabilir.
@Controller
- Sınıfın, dışardan gelen requestleri yakalaması gereken bir sınıf olduğu belirtilir.
- Annotation taramaları esnasınasında @Controller ve onun altındaki @RequestMapping tanımları taranır.
- Bu sebeple @RequestMapping ifadesini yalnızca @Controller tanımlı sınıflarda kullanabiliriz
- @Controller sınıf seviyesinde bir anotasyonken, @RequestMapping fonksiyon seviyesinde bir anotasyondur.
@RestController Nedir? @Controller ile @RestController Arasındaki Fark Nedir?
- @RestController tanımı @Controller tanımının özelleşmiş halidir.
- @ResponseBody varsayılan olarak tanımlanır.
- @RestController tanımlaması olan sınıflar için ekstradan @ResponseBody tanımlaması yapmaya gerek yoktur.
- Rest işlemlerinde @Controller tanımlaması yapılan sınıflarda @ResponseBody eklemek gerekir.
- Controller Spring MVC için bir View döndürürken, @RestController bir view döndürmez.
@ResponseBody ve @ResponseEntity
- Aynı işi yaparlar.
- Eldeki veriyi JSON olarak serialize edip geri gönderirler.
- @ResponseEntity geri döndürülecek mesajın içeriğiyle ilgili biraz daha fazla esneklik sağlar.
@RequestMapping
- Uygulama başlarken tüm annotation ifadeler ApplicationContext içinde depolanır.
- Spring Boot RequestMappingHandlerMapping (in WebMvcAutoConfiguration) gibi bir sürü Bean’i otomatik konfigüre eder.
- Bean başlatıldığında ApplicationContext içinde @Controller ve onun da üzeriden @RequestMapping tanımını arar.
- MappingRegistry (in AbstractHandlerMethodMapping) fonksiyonu üzerinde de işleme devam eder.
- DispatcherServlet merkezi HTTP istek yakalayıcısıdır.
- İstek geldiğinde bunu HandlerMapping interface’ini implemente eden sınıfları arar.
- Bean olarak tanımlanan RequestMappingHandlerMapping fonksiyonu da gelen istek için mapping gerçekleştirir.
Örnek :
@RequestMapping(value = "/api/products", method = RequestMethod.GET) @ResponseBody public String getFoosBySimplePath() { return "Get All Products"; }
@RequestMapping(value = "/api/products", method = RequestMethod.POST) @ResponseBody public String getFoosBySimplePath() { return "Product Saved"; }
Örnekten de anlaşılacağı gibi, uygulamanıza "/api/products" uzantılı bir URL üzerinden bir GET isteği geldiği zaman, uygulama "Get All Products" cevaı dönecektir. Şayet aynı URL üzerinden bir POST isteği gelirse, kullanıcıya "Product Saved" cevabı dönecektir.
@RequestBody
- HTTP isteğinin gövdesini deserialize ederek, tanımlanan sınıfın objesine dönüştürür.
- Bunu yaparken HttpMessageConverteres adlı Bean sınıfından faydalanır. (HTTP request/response işlemleri yapar)
- Gelen istediğin başlığını kontrol edip, istek gövdesini json’dan domain objesine deserialize eder.
@Entity
- Tanımlanan sınıfın bir JPA varlığı olduğunu belirtir.
- Uygulama çalıştıktan sonra veritabanı işlemlerinin buradaki verilere göre yapılacağı tanımlanır.
- Eğer @Entity veya @Table içinde ek bir belirtim yapılmadıysa, sınıf adı tablo adı olur.
- @Table belirtimi yalnızca veritabanı ile ilgili yapmak istediğimiz özel belirtimler için kullanılır.
- Entity sınıfı bir POJO sınıfıdır. Final yada Inner class olarak tanımlanamaz.
- Veritabanında oluşan tablodaki her satır bir entity set olarak tanımlanır.
@Entity ve @Repository Arasındaki Fark Nedir?
- Entity olarak tanımlanan sınıflarda her bir sınıf, veritabanındaki bir tabloya denk gelmektedir. Başka bir deyişle her bir Entity sınıfında, bir veritabanı tablosu modellenir. Tabloya ait isim ve tablodaki sütunlar, tipleriyle birlikte @Entity olarak tanımlanmış sınıf içerisinde belirtilirler.
- Repository sınıfı ise doğrudan veritabanı sorgularının gerçekleştirildiği ve veritabanından dönen cevabın yakalandığı bir sınıfır.
Daha fazla bilgi alabileceğiniz kaynaklar :
- Spring Conext https://dzone.com/articles/what-is-a-spring-context
- Basic Annotations https://stackoverflow.com/questions/1372876/how-and-where-are-annotations-used-in-java
- @Autowired https://stackoverflow.com/questions/3153546/how-does-autowiring-work-in-spring
- @Component,@Repository,@Service https://stackoverflow.com/questions/6827752/whats-the-difference-between-component-repository-service-annotations-in
- @Service https://stackoverflow.com/questions/47668871/what-is-a-spring-service-annotation
- @RequestMapping https://stackoverflow.com/questions/45329692/how-requestmapping-internally-works-in-spring-boot
- @RestController https://stackoverflow.com/questions/25242321/difference-between-spring-controller-and-restcontroller-annotation
- @ResponseBody ve @ResponseEntity https://stackoverflow.com/questions/22725143/what-is-the-difference-between-responseentityt-and-responsebody
- @RequestBody ve @ResponseBody https://www.baeldung.com/spring-request-response-body
- @RequestBody ve @ResponseBody http://websystique.com/springmvc/spring-mvc-requestbody-responsebody-example/
- @Entity https://spring.io/guides/gs/accessing-data-jpa/
Thanks you sharing good information visit Spring boot tutorials
YanıtlaSilyou're welcome
SilÇok faydalı oldu ,teşekkürler
YanıtlaSilFaydalı olmasına sevindim, değerli yorumunuz için ben teşekkür ederim
SilMükemmel bir yazı. Teşekkürler
YanıtlaSilBeğenmenize sevindim. Güzel yorumunuz için ben teşekkür ederim
SilGerçekten birçok noktada güzel bilgiler içeren bir yazı olmuş. Paylaştığın için teşekkürler.
YanıtlaSilYazının faydalı olabilmesine çok sevindim. Güzel yorumun ve geribildirimin için ben teşekkür ederim.
SilÇok temiz bir yazı ne eksik ne fazla :) tebrikler
YanıtlaSilGüzel yorumun ve geribildirimin için ben teşekkür ederim
Sil