IoC(Inversion of Control) Nedir ?

Kontrolün tersine evrilmesi demektir ve bizim nesnelerimizin dış kaynaktan alınması sürecidir. Bu süreci bizim için Spring Container yapar:

  1. Nesneleri oluşturma ve yönetme (IoC)
  2. Nesne bağımlılıklarını inject etme (Dependency Injection)

Örneğin bizim uygulamamızın bize bir tane "Teacher" isimli bir tane nesne vermesini istersek:

Spring Container'ın yapılandırmak (configuration) için 3 tane seçeneğimiz vardır.

  1. XML Configuration Dosyası (Eski)
  2. Java Annotations (Yeni)
  3. Java Source Code (Yeni)

Injection Types

Bizim nesnelerimize verileri enjekte edebilmek ve nesnelerimizi Spring de oluşturmak için 3 farklı yönteme değineceğiz.

  1. Constructor Injection
  2. Setter Injection
  3. Field Injection

Constructor Injection : Genelde spring geliştirme ekibi tarafından önerilen ve kullanılan injection yöntemidir ve gerekli bağımlılıklara ihtiyacımız olduğunda kullanmamız gereken injection yöntemidir.

Setter Injection : Eğer ki optional olarak dependencies ihtiyacımız varsa kullanamız gerekir.

Field Injection : Spring framework ekibinin önermediği bir injection yöntemidir çünkü unit testleri yapmak için kodu daha çok zorlaştırıyor.

Dependency injection sürecinde, Spring autowiring kullanabilir. Spring bizim istediğimiz class için gidip bakacak böyle bir class için uyuşan bir şey var mı (class yada interface) ve daha sonrasında spring otomatik olarak bunu inject edecektir bu sürece autowiring diyoruz.

Örnek :

Biz DemoController'ımızda Teacher için bir tane nesne isteyeceğiz.

  1. Spring @Component tanımlı annotationlara bakacak.
  2. Bakacak ki eğer ki bir tane class, Teacher interfacesini implement ediyor mu ?
  3. Eğer ki implement ediyorsa bunu inject et.

@Component annotationun ana amacı bizim sınıfımızı bir Spring bean olarak işaretlemesidir yani dependency injection için uygundur olmasını bildirir.

@Autowired annotationun ana amacı Spring'e bir dependecy'i inject etmesini söyler.

Constructor Injection

Bu süreçte biz injection sürecimizi Controller oluşturulur oluşturulmaz bizim için injection sürecini de yapmasını isteyeceğiz.

Teacher.java

public interface Teacher {
String getName();
}

MathTeacher.java

@Component
public class MathTeacher implements Teacher{
    @Override
    public String getName() {
      return "Minter Math";
    }
}

ConstructorInjectionRestController.java


@RestController
public class ConstructorInjectionRestController {
    private final Teacher teacher;
    @Autowired
    public ConstructorInjectionRestController(Teacher teacher) {
       this.teacher = teacher;
     }
    @RequestMapping(path="/injection/constructor",method=RequestMethod.GET)
    public String getTeacherName(){
      return this.teacher.getName();
    }
}


Not : Eğer ki biz sadece 1 tane constructorumuz varsa @Autowired annotationu opsiyonaeldir kullanmasakta olur.

İşin arka kısmında dönen olay ise şudur, Spring framework:


Teacher theTeacher = new MathTeacher();
ConstructorInjectionRestController constructorInjectionRestController = new ConstructorInjectionRestController(theTeacher); // şeklinde oluşturur.



Setter Injection

Burda da setter sürecinde Teacher nesnemizi oluşturacağız.

Teacher.java

public interface Teacher {
String getName();
}

MathTeacher.java

@Component
public class MathTeacher implements Teacher{
    @Override
    public String getName() {
      return "Minter Math";
    }    
}


SetterInjectionRestController.java


@RestController
public class SetterInjectionRestController {

    private Teacher teacher;

    @RequestMapping(path="/injection/setter",method=RequestMethod.GET)
    public String getTeacherName(){
      return this.teacher.getName();
    }

    @Autowired
    public void setTeacher(Teacher teacher){
      this.teacher = teacher;
    }

}




İşin arka kısmında dönen olay ise şudur, Spring framework:


Teacher theTeacher = new MathTeacher();
SetterInjectionRestController setterInjectionRestController = new SetterInjectionRestController(); 
setterInjectionRestController.setTeacher(theTeacher); // şeklinde oluşturur.


Field Injection

Spring developer ekibi tarafından önerilmeyen kullanım şeklidir.

Teacher.java


public interface Teacher {
    String getName();
}


MathTeacher.java

public interface Teacher {
    String getName();
}


FieldInjectionRestController.java

 @RestController
public class FieldInjectionRestController {
    @Autowired
    private Teacher teacher;
    
    @RequestMapping(path="/injection/field",method=RequestMethod.GET)
    public String getTeacherName(){
        return this.teacher.getName();
    }
}