Bean은 Spring이 관리하는 객체이다.
@Bean
public MyService myService(){
return new MyService();
}
- 반환하는 객체를 Bean으로 등록한다.
- 메서드명이 Bean의 이름으로 등록된다.
Bean의 이름이 중복된다면?
- 충돌이 일어난다.
- 주로 @Controller,@Service와 같은 애너테이션으로
@RestController
public class MemberController {
private MemberService memberService;
private MemberMapper memberMapper;
}
- MemberController는 memberService와 memberMapper를 의존한다.
- memberService와 memberMapper는 Controller보다 먼저 Bean으로 등록되어야한다.
Spring Bean의 기본 스코프
- singleton이다.(생성부터 소멸까지)
- singleton -> 해당 Bean 클래스에 대해 인스턴스를 1개만 생성

Spring에서 IoC 컨테이너란?
Bean을 생성하고, 의존성 주입하고, 생명 주기를 관리하는 중앙 관리 장치
이 역할을 수행하는 핵심 인터페이스가 BeanFactory / ApplicationContext
ApplicationContext란?
Spring 컨테이너의 구현체.
@Configuration
- 하나 이상의 @Bean 메서드를 정의한다.
- @Bean으로 등록된 메서드의 반환객체를 Bean으로 등록한다.
- @ComponentScan 범위 안일때 해당 클래스가 Bean이 된다.
//Bean의 이름 등록
@Configuration("configurationSection02")
public class ContextConfiguration {
@Bean
public Account accountGenerator(){
return new PersonalAccount("101-1111-2222",10000,3022);
}
//반환객체를 Bean이된다.
//이름은 따로 지정해주지 않으면 getMember가 된다.
@Bean
public MemberDTO getMember(){
return new MemberDTO(1,"010-1234-5678","kis2690@naver.com","곽인성",accountGenerator());
}
}
- accountGenerator로 PersonalAccount 하나 만들어짐
- getMember()로 MemberDTO 하나 만들어짐. 근데 accountGenerator()를 또 실행함
- 1번에서 만들어졌으므로, 이미 만들어진거 갖다 쓴다.
- Spring은 이미 있는건지 어떻게 알아? -> 프록시를 쓴다.
- @Configuration은 Proxy객체로 대체된다.
ComponentScan
@Component를 단다고 해서 Bean으로 등록되는 범위는 main과 같거나 하위 위치일 경우이다.
@SpringBootApplication
@ComponentScan(basePackages = "com.codeit.springbeanpractice.example03.service")
public class SpringBeanPracticeApplication {
public static void main(String[] args) {
ApplicationContext context =
SpringApplication.run(SpringBeanPracticeApplication.class, args);
context.getBean("memberService");
}
}
- @ComponentScan(basePackages = "com.codeit.springbeanpractice.example03.service")을 통해 특정 스캔 범위를 지정할 수 있다.
- @ComponentScan(basePackageClasses = {MemberService.class, MemberRepository.class})이런식으로 여러개도 가능.
@ComponentScan(excludeFilters = {})
을 사용하면 Scan에서 제외할것들을 지정.
생성자주입만 권장하는 이유
- 필드 주입은 결합도가 높다.
- 생성자 주입은 주입하는 객체 앞에 final을 붙일 수 있다. 따라서 객체 생성되는 시점에 초기화가 강제된다.
@Controller
public class MemberController {
private final MemberService memberService;
}
- final은 초기화가 필요하다.
- memberService의 값은 null이 들어가게 된다.
- final이 붙는다는건 직접 초기값을 지정해줘야한다.
- memberController가 만들어지는 시점에는 무조건 memberService의 초기값이 들어와야한다.
[초기값 만드는 두가지]
@Controller
public class MemberController {
private final MemberService memberService = new MemberService();
}
- 이런 경우는 결합도가 강해서 잘 안쓴다.
- 테스트가 거의 불가능하다
@Controller
public class MemberController {
private final MemberService memberService;
public MemberController(MemberService memberService){
this.memberService = memberService;
}
}
- Spring이 알아서 MemberController를 만들고 알아서 주입해줌.
- 생성자 주입은 null을 방지한다.
- final은 생성자 주입밖에 못쓴다.
[동일 타입 Bean 처리]
- 기본적으로 Spring은 주입을안한다.
- Spring은 파라미터 변수명을 우선으로 주입을 한다.(그치만 그렇다고 변수명으로 바꾸면 위험함.)
[NotificationService에 @Service를 붙였을때]
package com.codeit.springbeanpractice.example09;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
@Service
public class DependencyService {
// @Autowired(required = false) //이 Bean이 없을때는 무시하고 객체를 만든다.
@Autowired
@Nullable
private NotificationService notificationService;
public void sendNotification(){
notificationService.sendNotification();
}
}
- null이 아닌 객체가 생성된다.
- Spring이 자동으로 private NotificationService notificationService = new NotificationService();를 한다.
- @Service를 안붙이면 null로 들어가서 호출하면 NPE가 뜬다.
'코드잇 스프린트 > Spring 이론' 카테고리의 다른 글
| 애플리케이션의 각 계층에서 수행되는 입력값 검증의 범위와 책임 (0) | 2026.04.06 |
|---|---|
| 트랜잭션 ACID중 격리성(Isolation)이 보장되지 않을때 문제 (0) | 2026.04.01 |
| JPA에서 발생하는 N+1 문제의 발생 원인과 해결 방안(EAGER 는 JOIN이 아니다.) (1) | 2026.03.26 |
| 웹 API가 SOAP에서 REST로 전환된 이유 (0) | 2026.02.27 |
| Spring Framework 탄생 배경. (0) | 2026.01.26 |