본문 바로가기
Backend/Spring

Spring : @Autowired 어노테이션에 대해서

by 코딩쥐 2024. 10. 26.

@Autowired는 스프링 프레임워크에서 의존성 주입(Dependency Injection)을 수행하는 어노테이션이다. @Autowired 어노테이션을 사용하면 스프링이 자동으로 해당 클래스의 필드, 생성자 또는 메서드에 의존성을 주입해준다. 수동으로 객체를 생성하고 관리할 필요가 없이, 스프링 컨테이너가 이를 관리한다. 

 

1. 빈으로 생성 할 클래스들을 생성한다.

(1) @Component 어노테이션을 사용하여 Fruit 클래스를 빈으로 등록한다. Food 클래스는 name이라는 멤버변수를 설정하고, getter와 setter 메서드를 선언한다. 

package com.example.project1.beans;

import org.springframework.stereotype.Component;

//@Component 어노테이션 선언
@Component
public class Fruit {
    private String name;

    //Getter 메서드
    public String getName() {
        return name;
    }

    //Setter 메서드
    public void setName(String name) {
        this.name = name;
    }

    //toString 메서드 : 과일의 이름만 return 하게 메서드 오버라이드
    @Override
    public String toString() {
        return name;
    }
}

 

(2) @Component 어노테이션을 사용하여 Eat 클래스를 빈으로 등록한다. Eat 클래스는 Fruit 타입을 가진 food 멤버변수를 설정하고, getter 메서드를 정의한다. 

package com.example.project1.beans;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Eat {
    private Fruit food;

    public Eat(Fruit food) {
        this.food = food;
    }

    public String getFood() {
        return food + "를 먹습니다.";
    }
}

 

2. @Autowired 어노테이션을 사용한다.

@Autowired 어노테이션을 사용하여 빈을 주입하는 방법은 세 가지 방법으로 수행할 수 있다. 생성자 주입, 필드 주입, 메서드 주입이며 주로 사용되는 방식은 생성자 주입이다. 

  • 생성자 주입 :  클래스를 생성할 때 생성자의 매개변수로 의존성 주입. 스프링에서는 생성자에 @Autowired를 명시적으로 작성하지 않아도 자동으로 의존성을 주입할 수 있다. 단, 생성자가 하나만 존재하고 @Component와 같은 어노테이션이 있어야만 생략이 가능하다. 
    @Autowired // 생성자 주입
    public Eat(Fruit food) {
        this.food = food;
    }

 

  • 필드(멤버변수) 주입 : 클래스 멤버에 직접 사용하여 의존성 주입
    @Autowired //필드(멤버변수) 주입
    private Fruit food;

 

  • 메서드 주입 : setter 메서드에 의존성을 주입. 아래와 같이 setter 메서드가 setFood일 경우 스프링은 'food'라는 멤버변수를 찾아 해당 멤버변수의 타입에 맞는 객체를 인스턴스로 주입한다. 
    @Autowired // 메서드 주입
    public void setFood(Fruit food) {
        this.food = food;
    }

 

아래의 예제에서는 생성자에 @Autowired 어노테이션을 사용하여 Fruit 빈을 Eat 클래스에 주입한다. 생성자를 주입하고, food에 대한 데이터를 설정한다. 

package com.example.project1.beans;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Eat {
    private Fruit food;

    // 생성자 주입
    @Autowired
    public Eat(Fruit food) {
        this.food = food;
        this.food.setName("사과"); // 생성자에서 데이터 설정
    }

    public String getFood() {
        return food + "를 먹습니다.";
    }
}


3. Eat bean을 사용하여 출력한다. 

package com.example.project1;

import com.example.project1.beans.Eat;
import com.example.project1.beans.Fruit;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

@SpringBootApplication
public class Project1Application {

	public static void main(String[] args) {
		ApplicationContext app = SpringApplication.run(Project1Application.class, args);

		// Eat 빈을 가져와서 인스턴스를 생성한다.
		Eat apple = app.getBean(Eat.class);

		// 결과 출력
		System.out.println(apple.getFood()); // "사과를 먹습니다." 출력
	}
}

 


만약 @Autowired를 작성하지 않았으면 아래와 같이 수동으로 인스턴스를 생성해서, 데이터를 설정하는 과정이 필요하다. 

// Fruit.java : 변경없음 

@Component
public class Fruit {
    private String name;

    //Getter 메서드
    public String getName() {
        return name;
    }

    //Setter 메서드
    public void setName(String name) {
        this.name = name;
    }

    //toString 메서드 : 과일의 이름을 return할 수 있게 메서드 오버라이드
    @Override
    public String toString() {
        return name;
    }
}

 

Eat클래스는 Fruit 객체를 food라는 멤버변수로 갖게되며, 해당하는 객체의 메서드 및 필드를 사용하기 위해서 setter 메서드를 통해서 의존성을 설정한다. 즉 setFood(Fruit food)라는 메서드를 호출하면 Fruit 객체를 참조하게 되고, Fruit 객체 안에 있는 메서드(getName(), setName())를 사용할 수 있다.

//Eat.java : setter 메서드를 삽입해서 Fruit 클래스의 메서드 및 필드를 사용한다. 

@Component
public class Eat {
    private Fruit food;

    // setter 메서드를 통해 의존성 설정
    public void setFood(Fruit food) {
        this.food = food;
        this.food.setName("사과");
    }

    public String getFood() {
        return food + "를 먹습니다.";
    }
}

 

Project1Application 클래스의 main 메서드는 스프링 애플리케이션을 실행합니다. Eat과 Fruit 빈을 가져와 각각 인스턴스를 생성하고, Eat 객체에 Fruit 객체를 설정한다.

// Project1Application.java : Eat 객체를 생성한 후 Fruit 인스턴스를 생성하여 수동으로 삽입한다.

@SpringBootApplication
public class Project1Application {
	public static void main(String[] args) {
		ApplicationContext app = SpringApplication.run(Project1Application.class, args);

		// Eat 빈을 가져온 후, Fruit 빈을 가져옴
		Eat apple = app.getBean(Eat.class);
		Fruit fruit = app.getBean(Fruit.class);

		// Eat의 food(Fruit의 인스턴스)를 설정
		apple.setFood(fruit);

		// 결과 출력
		System.out.println(apple.getFood()); // "사과를 먹습니다." 출력
	}
}

 

@Autowired 사용하는 경우에는 스프링이 Eat 클래스의 생성자에 Fruit 빈을 자동으로 주입하기 때문에, setter 메서드를 통해서 Fruit객체를 수동으로 주입하지 않아도 된다. 또한 Fruit의 setName과 같은 데이터 설정을 생성자 내에서 할 수 있어서 데이터 초기화가 가능하다. 반면 @Autowired를 사용하지 않을 경우에는 setFood(Fruit food)와 같은 setter메서드를 사용해서 Fruit 객체를 수동으로 주입해야한다.