Spring

@Component , @Autowired, @Configuration, @ComponentScan

wintertreey 2024. 7. 4. 18:19

우리가 Spring을 사용하는 수 많은 이유중에 대표적인 장점을 꼽으라면 의존성 주입 컨테이너에 관한 내용을 빼놓을 수 없다. 스프링은 자바 빈을 찾아서 ApplicationContext라고 하는 의존성 주입 컨테이너 오브젝트에 등록을 한다. 그리고 애플리케이션이 돌다가 어떤 오브젝트가 필요하다면 의존하는 오브젝트를 찾아서 연결해준다.

 

그렇다면 스프링은 어떻게 자바 빈을 찾아가지고 의존성 주입 컨테이너에 등록하는걸까?? @Component 어노테이션으로 이 클래스를 자바 빈으로 등록하라고 알려줄 수 있다.

 

@Component

@Component 어노테이션을 붙이면 이 클래스를 자바 빈으로 등록시키라고 알려줄 수 있다. 해당 어노테이션이 명시되어 있으면 Spring이 자동으로 클래스의 인스턴스를 생성해준다.

 

단,  @ComponentScan이라는 어노테이션이 존재해야만 한다.

(Spring Boot 에선 이것도 자동적으로 처리해주긴 함.)

 

Sender.java

package anno1_auto;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component//싱글톤 패턴으로 Sender 객체 생성. 즉 xml 작업 불요. 
//@Component("sen")
//@Scope("singleton")
public class Sender {
	public void show() {
		System.out.println("Sender클래스의 show메소드 수행");
	}
}

 

@Component("sen") 

Sender클래스 객체변수명 sender 기본값. 다르게 하고싶을때 적어준다. 
@Scope("singleton")

기본이 싱글톤. 다르게 하고싶을때 적어준다. 

 

@Controller @Service @Repository

@component 의 하위버젼 어노테이션이다. 

같은 역할을 하지만 좀더 세부적으로 목적에 맞춰서 사용하게 된다. 

 

 

 

 

계층(Layers)별 annotation.

 

 

@Controller Application Layer 클라이언트로 부터 요청이 왔을 때, 데이터입출력을 제어
@Service Domain Layer 어플리케이션 중심. 업무처리 담당.
@Repository Infrastructure Layer DB에 대한 영속성(persistence) 등을 담당

 

SenderProcess.java 의 상단부분

 
package anno1_auto;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

//@Component
@Service// 이 클래스의 목적에 맞춰서 씀. 
public class SenderProcess {

 

@Service("senderProcess")
@Scope("singleton") 이 두줄은 @Service와 같은 의미이다.  이런 부분은 역시 Component와 비슷.

 


 

@Autowired

@Autowired 어노테이션은 @Component와 함께 사용된다. 이 어노테이션을 달면 ApplicationContext에 필요한 종속성의 인스턴스를 자동으로 주입해준다.

주의!! name에 의한 매핑이 아닌, type으로 매핑!! 

 

package anno1_auto;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

@Service// 이 클래스의 목적에 맞춰서 씀. 

public class SenderProcess {
	
	@Autowired //멤버필드 주입 : 간단. 테스트불편. 제일 많이사용.
	private Sender sender; 
	
	/*
	@Autowired //setter 주입: 코드가 장황.
	public void setSender(Sender sender) {
		this.sender = sender;
	}
	
	@Autowired //constructor 주입: 불변성과 테스트가 편하지만, 생성자가 너무 많아짐.
	public SenderProcess(Sender sender) {
		this.sender = sender;
	}
	*/
	
	public Sender getSender() {
		return sender;
	}
	public void dispData() {
		sender.show();
	}
}

 

@Autowired를 통해 자동으로 Sender타입의 인스턴스 주소를 객체변수sender에 넣어준다. 

 

DI(dependency Injection, 의존성 주입)의 종류 및 장단점 

필드 주입

  1. 장점
    • 의존성 주입하기가 쉬움
  2. 단점
    • 외부에서 접근이 불가능하기 때문에 테스트시 객체를 수정할 수 없음
    • final 키워드를 붙이기 못하기 때문에 객체의 불변을 보장하지 못함
    • DI 프레임워크가 존재해야만 가능한 방식이기 때문에, 프레임워크에 의존적임
    • SRP 위반

Setter Injection

  1. 장점
    • 의존성이 선택적으로 필요한 경우에 사용 가능
    • 의존성이 변경될 가능성이 있는 경우에 사용 가능
  2. 단점
    • final 키워드를 붙이기 못하기 때문에 객체의 불변을 보장하지 못함
    • 구현체를 주입해주지 않아도 생성이 가능해지는데, 이때 메서드를 호출하면 NullPointerException이 발생하게 됨. 즉, 주입이 필요한 객체가 주입되지 않아도 객체를 생성할 수 있게 된다는 것이 문제

Constructor Injection 

  1. 장점
    • 의존 객체 주입 없이는 객체를 생성하지 못하도록 강제할 수 있음
    • final 키워드 사용 가능
    • 순환 의존성을 컴파일 단계에서 잡아낼 수 있다.
    • 생성자의 매개변수로 의존성이 추가되기 때문에 의존성이 많아질 경우 개발자가 자연스레 리팩터링을 생각하게 함
  2. 특이사항
    • 단일 생성자인 경우에 @Autowired 키워드 없어도 됨

 

이 어노테이션의 장점은 

앞서 생성자를 선언하고 일일이 constructor injection, setter injection 을 수행했던 xml파일(init.xml, configuration.xml 등)을 만들지 않아도 된다는것이다.

 

바로 출력용 메인 파일을 만든다.

Main.java

package anno1_auto;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = "anno1_auto")
public class Main1 {
	
	public static void main(String[] args) {
		//@Autowired에 대한 메인
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main1.class);
		SenderProcess process = context.getBean("senderProcess", SenderProcess.class);
		process.dispData();
		
	}
}

 

@Component에서 설명할때 짝궁이라고 해줬던 어노테이션 @ComponentScan을 써줘야 @Component를 선언해준 클래스들을 읽어줄수있다. 

 

콘솔창에 출력결과물

 

@Configuration이란?

@Configuration은 빈을 등록할 수 있는 어노테이션 중 하나이다.

Spring 공식 문서에서는 다음과 같이 설명하고 있다.

Indicates that a class declares one or more @Bean methods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime

 

@Configuration 어노테이션을 사용하면, 하나 이상의 @Bean이 붙은 메서드가 포함된 빈 설정용 클래스를 만들 수 있다.

스프링 컨테이너는 @Bean이 붙은 메서드를 통해 빈을 생성한다.

 

@ComponentScan

 어노테이션 선언해준 클래스들이 이시점에서 비로소 인스턴스가 됨. 

그전엔 선언해준것뿐이었다.


https://velog.io/@_koiil/Spring-Component%EC%99%80-Repository-Service-Controller

 

[Spring] @Component와 @Repository, @Service, @Controller

어떤 때 무엇을 써야할까요

velog.io

https://cafe.daum.net/flowlife/HrhB/35

 

Annotation 알아보기

https://velog.io/@gillog/Spring-Annotation-%EC%A0%95%EB%A6%AC 스프링 프레임워크가 버전업 될 때 마다 새로운 어노테이션이 계속 등장하고 있는 실정이다!!! @Scope : Spring 에서 관리하는 Bean(객체)은 싱글턴 상

cafe.daum.net

https://coding-nyan.tistory.com/158

 

[Spring Boot] @Component에 대한 이해

우리가 Spring을 사용하는 수 많은 이유중에 대표적인 장점을 꼽으라면 의존성 주입 컨테이너에 관한 내용을 빼놓을 수 없다. 스프링은 자바 빈을 찾아서 ApplicationContext라고 하는 의존성 주입 컨

coding-nyan.tistory.com

https://easthshin.tistory.com/9

 

DI(Dependency Injection)의 종류와 장단점

필드 주입 장점 의존성 주입하기가 쉬움 단점 외부에서 접근이 불가능하기 때문에 테스트시 객체를 수정할 수 없음 final 키워드를 붙이기 못하기 때문에 객체의 불변을 보장하지 못함 DI 프레임

easthshin.tistory.com

https://tecoble.techcourse.co.kr/post/2023-05-22-configuration/

 

@Configuration은 어떻게 빈을 등록하고, 싱글톤으로 관리할까?

tecoble.techcourse.co.kr