✍️
dodeon
  • 개발왕, 도던
  • 스프링 시큐리티 인 액션
    • 오늘날의 보안
    • 안녕! 스프링 시큐리티
    • 사용자 관리
    • 암호 처리
    • 인증 구현
    • 실전: 작고 안전한 웹 애플리케이션
    • 권한 부여 구성: 액세스 제한
    • 권한 부여 구성: 제한 적용
    • 필터 구현
    • CSRF 보호와 CORS 적용
    • 실전: 책임의 분리
    • OAuth 2가 동작하는 방법
    • OAuth 2: 권한 부여 서버 구현
  • 스프링 고급편
    • 스레드 로컬
    • 템플릿 메서드 패턴과 콜백 패턴
    • 프록시 패턴과 데코레이터 패턴
  • 스프링 입문
    • 프로젝트 환경설정
    • 스프링 웹 개발 기초
    • 회원 관리 예제 - 백엔드
    • 스프링 빈과 의존 관계
    • 회원 관리 예제 - MVC
    • 스프링 DB 접근 기술
      • JDBC
      • JPA
    • AOP
  • 스프링 핵심 원리
    • 객체 지향 설계와 스프링
      • 스프링의 탄생
      • 객체 지향 프로그래밍
      • 좋은 객체 지향 설계의 원칙
      • 객체 지향 설계와 스프링
    • 스프링 핵심 원리 이해
      • 회원 도메인 개발
      • 주문 도메인 개발
    • 객체 지향 원리 적용
      • 관심사의 분리
      • 새로운 구조와 정책 적용
      • 정리
      • IoC, DI, 컨테이너
      • 스프링으로 전환하기
    • 스프링 컨테이너와 스프링 빈
      • 스프링 빈 기본 조회
      • 동일 타입이 둘 이상일 때 조회
      • 상속일 때 조회
      • BeanFactory와 ApplicationContext
      • 다양한 설정 형식
      • 스프링 빈 설정 메타 데이터
    • 싱글턴 컨테이너
      • @Configuration과 싱글턴
    • 컴포넌트 스캔
      • 탐색 위치와 기본 탐색 대상
      • 필터와 중복 등록
    • 의존 관계 자동 주입
      • 롬복과 최신 트렌드
      • 조회 빈이 2개 이상일 때
      • 애너테이션 직접 만들기
      • 조회한 빈이 모두 필요할 때
      • 올바른 실무 운영 기준
    • 빈 생명 주기 콜백
      • 인터페이스 방식
      • 메서드 지정 방식
      • 애너테이션 방식
    • 빈 스코프
      • 프로토타입 스코프
      • Provider
      • 웹 스코프
  • 스프링 MVC
    • 웹 애플리케이션 이해
      • 서버
      • 서블릿
      • 멀티 스레드
      • HTML, HTTP API, CSR, SSR
      • 자바 백엔드 웹 기술 역사
    • 서블릿
      • HttpServletRequest
      • HTTP 요청 데이터
      • HttpServletResponse
      • HTTP 응답 데이터
    • 서블릿, JSP, MVC 패턴
      • 서블릿으로 만들기
      • JSP로 만들기
      • MVC 패턴
    • MVC 프레임워크 만들기
      • 프론트 컨트롤러 패턴
      • View 분리
      • Model 추가
      • 단순하고 실용적인 컨트롤러
      • 유연한 컨트롤러
      • 정리
    • 스프링 MVC의 구조 이해
      • 스프링 MVC 전체 구조
      • 핸들러 매핑과 핸들러 어댑터
      • 뷰 리졸버
      • 스프링 MVC 시작하기
      • 스프링 MVC 컨트롤러 통합
      • 스프링 MVC 실용적인 방식
    • 스프링 MVC 기본 기능
      • 프로젝트 생성
      • 로깅
      • 요청 매핑
      • HTTP 요청의 기본 및 헤더 조회
      • HTTP 요청 파라미터
      • HTTP 요청 메시지
      • HTTP 응답
      • HTTP 메시지 컨버터
      • 요청 매핑 핸들러 어댑터
    • 스프링 MVC 웹 페이지 만들기
    • 메시지, 국제화
      • 스프링 메시지 소스
    • Validation
      • BindingResult
      • FieldError, ObjectError
      • 오류 코드와 메시지 처리
      • Validator 분리
    • Bean Validation
      • Form 전송 객체 분리
      • HTTP 메시지 컨버터
    • 로그인
      • 쿠키
      • 세션
      • 서블릿 HTTP 세션
      • 서블릿 필터
      • 스프링 인터셉터
      • ArgumentResolver 활용
    • 예외 처리와 오류 페이지
      • 오류 화면 제공
      • 필터
      • 인터셉터
      • 스프링 부트 오류 페이지
    • API 예외 처리
      • 스프링 부트 기본 오류 처리
      • HandlerExceptionResolver
      • ExceptionResolver
      • ControllerAdvice
    • 스프링 타입 컨버터
      • Converter
      • ConversionService
      • 뷰 템플릿에 적용하기
      • Formatter
    • 파일 업로드
      • 서블릿과 파일 업로드
      • 스프링과 파일 업로드
      • 파일 업로드 및 다운로드 예제
  • 자바 ORM 표준 JPA 프로그래밍
    • JPA 소개
    • JPA 시작하기
    • 영속성 관리
      • 영속성 컨텍스트
      • 플러시
      • 준영속 상태
    • Entity 매핑
      • 객체와 테이블 매핑
      • 데이터베이스 스키마 자동 생성
      • 필드와 칼럼 매핑
      • 기본 키 매핑
      • 실전 예제
    • 연관 관계 매핑
      • 단방향 연관 관계
      • 양방향 연관 관계
      • 실전 예제
    • 다양한 연관 관계 매핑
      • 다대일
      • 일대다
      • 일대일
      • 다대다
      • 실전 예제
    • 고급 매핑
      • 상속 관계 매핑
      • 매핑 정보 상속
      • 실전 예제
    • 프록시와 연관관계 관리
      • 프록시
      • 즉시 로딩과 지연 로딩
      • 영속성 전이와 고아 객체
      • 실전 예제
    • 값 타입
      • 기본값 타입
      • 임베디드 타입
      • 값 타입과 불변 객체
      • 값 타입의 비교
      • 값 타입 컬렉션
      • 실전 예제
    • 객체 지향 쿼리 언어 - 기본
      • 기본 문법과 쿼리 API
      • 프로젝션
      • 페이징
      • 조인
      • 서브 쿼리
      • JPQL 타입 표현과 기타 식
      • 조건식
      • JPQL 함수
    • 객체 지향 쿼리 언어 - 중급
      • 경로 표현식
      • fetch join
      • 다형성 쿼리
      • Entity 직접 사용
      • Named 쿼리
      • 벌크 연산
  • 스프링 부트와 JPA 활용 - 웹 애플리케이션 개발
    • 프로젝트 환경설정
    • 도메인 분석 설계
      • 도메인 분석 설계
      • Entity 클래스 개발
      • Entity 설계 시 주의점
    • 애플리케이션 아키텍처
    • 회원 도메인 개발
    • 상품 도메인 개발
    • 주문 도메인 개발
      • Entity, 리포지토리, 서비스 개발
      • 주문 기능 테스트
      • 주문 검색 기능 개발
    • 웹 계층 개발
      • 변경 감지와 병합
  • 스프링 부트와 JPA 활용 - API 개발과 성능 최적화
    • API 개발 기본
      • 회원 등록 API
      • 회원 수정 API
      • 회원 조회 API
    • 지연 로딩과 조회 성능 최적화
      • Entity 직접 노출
      • Entity를 DTO로 변환
      • JPA에서 DTO 직접 조회
    • 컬렉션 조회 최적화
      • Entity 직접 노출
      • Entity를 DTO로 변환: 페치 조인
      • Entity를 DTO로 변환: 페이징과 한계 돌파
      • DTO 직접 조회
      • DTO 직접 조회: 컬렉션 조회 최적화
      • DTO 직접 조회: 플랫 데이터 최적화
      • 정리
    • OSIV와 성능 최적화
  • 스프링 데이터 JPA
    • 예제 도메인 모델
    • 공통 인터페이스 기능
      • 순수 JPA 기반 리포지토리
      • 공통 인터페이스 설정
    • 쿼리 메서드 기능
      • JPA Named Query
      • @Query
      • 파라미터 바인딩
      • 반환 타입
      • 페이징과 정렬
      • 벌크성 수정 쿼리
      • @EntityGraph
      • JPA Hint & Lock
    • 확장 기능
      • 사용자 정의 리포지토리
      • Auditing
      • Web 확장
    • 스프링 데이터 JPA 분석
    • 나머지 기능
      • Specifications
      • Query By Example
      • Projections
      • Native Query
  • Querydsl
    • 프로젝트 환경 설정
    • 예제 도메인 모델
    • 기본 문법
      • JPQL vs Querydsl
      • Q-Type 활용
      • 검색 조건
      • 결과 조회
      • 정렬
      • 페이징
      • 집합 함수
      • 조인
      • 서브 쿼리
      • Case 문
      • 상수, 문자 더하기
    • 중급 문법
      • 프로젝션과 결과 반환
      • 동적 쿼리
      • 수정, 삭제 벌크 연산
      • SQL Function 호출
    • 순수 JPA와 Querydsl
      • 순수 JPA 리포지토리와 Querydsl
      • 동적 쿼리와 성능 최적화 조회
      • 조회 API 컨트롤러 개발
    • 스프링 데이터 JPA와 Querydsl
      • 스프링 데이터 페이징 활용
      • 스프링 데이터 JPA가 제공하는 Querydsl 기능
  • 데이터 접근 핵심 원리
    • JDBC 이해
      • JDBC와 최신 데이터 접근 기술
      • 데이터베이스 연결
      • JDBC 개발
  • 백엔드 시스템 실무
    • CPU bound 애플리케이션
      • CPU를 극단적으로 사용하는 애플리케이션
      • 스트레스 테스트 툴로 성능 측정
      • Dockerized 애플리케이션 GCP 배포
      • Jenkins를 이용한 배포
    • CPU bound 애플리케이션 무중단 배포
      • nginx를 통한 로드밸런싱 구성
      • 서버를 늘려서 성능 측정
    • 배포 자동화와 협업을 위한 Git
      • GitHub Webhook과 jenkins로 배포 자동화
      • 머지할 때 발생하는 충돌 해결하기
      • 실무에서 유용한 Git 꿀팁
    • I/O bound 애플리케이션
    • Message Queue를 도입하여 데이터 유실 방지
      • 스트레스 테스트
    • 검색과 분석을 위한 저장소 ElasticSearch
    • Kubernetes
  • 모든 개발자를 위한 HTTP 웹 기본 지식
    • 인터넷 네트워크
      • IP
      • TCP, UDP
      • PORT
      • DNS
    • URI와 웹 브라우저 요청 흐름
    • HTTP 기본
      • 클라이언트-서버 구조
      • stateful, stateless
      • 비 연결성
      • HTTP 메시지
    • HTTP 메서드
    • HTTP 메서드 활용
    • HTTP 상태 코드
    • HTTP 헤더 - 일반
      • 표현
      • 콘텐츠 협상
      • 전송 방식
      • 정보
      • Authorization
      • 쿠키
    • HTTP 헤더 - 캐시
      • 검증 헤더와 조건부 요청
      • 조건부 요청 헤더
      • 프록시 캐시
      • 캐시 무효화
  • 김영한의 실전 자바
    • 제네릭
  • 예제로 배우는 스프링 입문
    • 예제로 배우는 스프링 입문(개정판)
      • PetClinic 예제
      • 스프링 IoC
      • 스프링 AOP
      • 스프링 PSA
  • 스프링 프레임워크 핵심 기술
    • 스프링 프레임워크 핵심 기술
      • IoC 컨테이너와 빈
        • 스프링 IoC 컨테이너와 빈
        • ApplicationContext와 빈 설정
        • @Autowired
        • @Component와 컴포넌트 스캔
        • 빈의 스코프
        • Environment
        • MessageSource
        • ApplicationEventPublisher
        • ResourceLoader
      • Resource/Validation
        • Resource 추상화
        • validation 추상화
      • 데이터 바인딩 추상화
      • SpEL
      • 스프링 AOP
      • Null-Safety
  • 스프링 부트 개념과 활용
    • 스프링 부트 원리
      • 자동 설정
      • 내장 서버
        • 컨테이너와 서버 포트
        • HTTPS와 HTTP2
      • 독립적으로 실행 가능한 JAR
    • 스프링 부트 활용
      • Spring Application
      • 외부 설정
      • 프로파일
      • 로깅
      • 테스트
      • Spring Boot Devtools
    • 스프링 웹 MVC
      • 소개
      • HttpMessageConverters
      • ViewResolver
      • 정적 리소스
      • 웹 JAR
      • index 페이지와 파비콘
      • ExceptionHandler
      • Spring HATEOAS
      • CORS
  • THE JAVA
    • JVM 이해하기
      • 자바, JVM, JDK, JRE
      • JVM 구조
      • 클래스 로더
      • Heap
      • Garbage Collector
    • 리플렉션
      • 클래스 정보 조회
  • The Java - Test
    • JUnit 5
      • JUnit 시작하기
      • JUnit 시작하기
    • Mockito
Powered by GitBook
On this page
  • 빈이 없거나 하나인 경우
  • 생성자
  • Setter
  • 필드
  • 빈이 여러 개인 경우
  • @Primary
  • @Qualifier
  • 해당 타입의 빈 모두 주입
  • 클래스 이름 지정
  • 동작 원리
  • BeanPostProcessor
  • AutowiredAnnotationBeanPostProcessor
  • PostConstruct
  • 정리

Was this helpful?

  1. 스프링 프레임워크 핵심 기술
  2. 스프링 프레임워크 핵심 기술
  3. IoC 컨테이너와 빈

@Autowired

빈이 없거나 하나인 경우

생성자

@Service
public class BookService {
    BookRepository bookRepository;

    @Autowired
    public BookService(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }
}
public class BookRepository {
}
  • 생성자 주입 시 BookRepository에 @Repository를 붙이지 않으면 에러가 난다.

  • 객체를 생성할 때 해당하는 빈을 찾지 못해 실패하기 때문이다.

  • 다른 방법에 비교해 인스턴스를 아예 생성할 수 없다.

Tip

  • 보통 Repository면 @Component보다는 @Repository로 빈 설정 해주는 것이 좋다.

  • 그래야 나중에 Repository에만 할 수 있는 설정이나 AOP 적용이 수월하다.

Setter

@Service
public class BookService {
    BookRepository bookRepository;

    @Autowired
    public void setBookRepository(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }
}
public class BookRepository {
}
  • Setter로 주입할 때도 @Repository 애너테이션이 없을 때 에러가 난다.

    • Setter라면 적어도 BookService 자체의 빈/인스턴스는 만들 수 있어야 하는 게 아닌가?

    • 맞다. 하지만 @Autowired가 있기 때문에 BookService 빈을 만들 때 의존성 주입을 시도하게 되므로 실패하는 것이다.

만약 이 의존성이 필수적인 게 아니라면 아래와 같이 설정할 수 있다.

@Service
public class BookService {
    BookRepository bookRepository;

    @Autowired(required = false)
    public void setBookRepository(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }
}

그럼 BookService 인스턴스만 생성되고 BookRepository는 의존성 주입이 안된채로 빈이 등록된다.

필드

@Service
public class BookService {
    @Autowired(required = false)
    BookRepository bookRepository;
}

필드 주입에도 똑같이 옵션을 지정할 수 있다.

빈이 여러 개인 경우

@Service
public class BookService {
    @Autowired
    BookRepository bookRepository;
}
public interface BookRepository {
}
@Repository
public class MyBookRepository implements BookRepository {
}
@Repository
public class KeesunBookRepository implements BookRepository {
}
  • 같은 BookRepository를 구현하는 클래스가 여러 개라면 BookService는 BookRepository를 주입할 수 없다.

@Primary

@Repository
@Primary
public class KeesunBookRepository implements BookRepository {
}
  • 여러 개의 빈 중에 이 빈을 먼저 주입해달라고 할 때 사용한다.

class me.whiteship.autowired.KeesunBookRepository
  • ApplicationRunner를 활용해 주입된 빈을 출력하면 위와 같이 나오는 걸 확인할 수 있다.

@Qualifier

  • 적용할 빈 이름을 @Qualifier에 추가해준다.

  • 빈이 등록될 때 이름의 기본값은 클래스 이름의 앞 부분을 소문자로 바꾼 것이다.

@Service
public class BookService {
    @Autowired
    @Qualifier("keesunBookRepository")
    BookRepository bookRepository;

    public void printBookRepository() {
        System.out.println(bookRepository.getClass());
    }
}
@Repository
public class KeesunBookRepository implements BookRepository {
}

하지만 @Primary가 좀 더 type-safe하므로 @Primary를 추천한다.

해당 타입의 빈 모두 주입

@Repository
public class KeesunBookRepository implements BookRepository {
}
@Repository
public class MyBookRepository implements BookRepository {
}
@Service
public class BookService {
    @Autowired
    List<BookRepository> bookRepositories;

    public void printBookRepository() {
        this.bookRepositories.forEach(System.out::println);
    }
}

List를 이용해 모든 빈을 다 주입 받을 수도 있다.

me.whiteship.autowired.KeesunBookRepository@172ca72b
me.whiteship.autowired.MyBookRepository@5bda80bf

확인하면 두 Repository 모두 주입 받았음을 알 수 있다.

클래스 이름 지정

빈을 주입할 때는 타입을 먼저 본 뒤 이름을 본다.

@Service
public class BookService {
    @Autowired
    // 이름 지정
    BookRepository myBookRepository;

    public void printBookRepository() {
        System.out.println(myBookRepository.getClass());
    }
}

그래서 주입할 때 특정 클래스 이름을 그대로 쓰면 그 클래스가 주입된다. 하지만 이 방법은 추천하지 않는다.

동작 원리

BeanPostProcessor 라는 빈 라이프 사이클 인터페이스의 구현체에 의해 동작한다. 다음은 표준 빈 라이프 사이클이다.

  1. BeanNameAware's setBeanName

  2. BeanClassLoaderAware's setBeanClassLoader

  3. BeanFactoryAware's setBeanFactory

  4. EnvironmentAware's setEnvironment

  5. EmbeddedValueResolverAware's setEmbeddedValueResolver

  6. ResourceLoaderAware's setResourceLoader (only applicable when running in an application context)

  7. ApplicationEventPublisherAware's setApplicationEventPublisher (only applicable when running in an application context)

  8. MessageSourceAware's setMessageSource (only applicable when running in an application context)

  9. ApplicationContextAware's setApplicationContext (only applicable when running in an application context)

  10. ServletContextAware's setServletContext (only applicable when running in a web application context)

  11. postProcessBeforeInitialization methods of BeanPostProcessors

  12. InitializingBean's afterPropertiesSet

  13. a custom init-method definition

  14. postProcessAfterInitialization methods of BeanPostProcessors

BeanPostProcessor

  • 새로 만든 빈 인스턴스를 수정할 수 있는 라이프 사이클 인터페이스

  • 빈의 인스턴스를 만든 후 초기화할 때 Initialization 라이프 사이클이 있는데, 이 라이프 사이클 앞/뒤로 부가적인 작업을 할 수 있는 또 다른 라이프 사이클 콜백이다.

  • 11. postProcessBeforeInitialization, 14. postProcessAfterInitialization 메서드 같은 콜백을 제공한다.

AutowiredAnnotationBeanPostProcessor

  • BeanPostProcessor를 상속하며 @Autowired, @Value, @Inject 애너테이션을 처리해준다.

  • 즉, 11. postProcess**Before**Initialization 단계에서 @Autowired가 붙은 의존성을 주입한다.

PostConstruct

@Service
public class BookService {
    @Autowired
    BookRepository myBookRepository;

    // 이제 Runner는 필요없다.
    @PostConstruct
    public void setup() {
        System.out.println(myBookRepository.getClass());
    }
}
  • @PostConstruct 단계에서는 이미 빈이 주입된 상태다.

  • 12. InitializingBean's afterPropertiesSet 단계에서 작업한다.

  • 이제 Runner 없이도 정보를 출력할 수 있다. 출력되는 위치만 조금 다르다.

2020-03-16 13:33:18.519  WARN 14600 --- [           main] o.s.boot.StartupInfoLogger               : InetAddress.getLocalHost().getHostName() took 5005 milliseconds to respond. Please verify your network configuration (macOS machines may need to add entries to /etc/hosts).
2020-03-16 13:33:23.524  INFO 14600 --- [           main] me.whiteship.autowired.DemoApplication   : Starting DemoApplication on macbook.local with PID 14600 (/Users/sojeong/dev/IntelliJ-workspace/spring-keesun-baik/spring-framework-core-02-autowired/target/classes started by sojeong in /Users/sojeong/dev/IntelliJ-workspace/spring-keesun-baik)
2020-03-16 13:33:23.525  INFO 14600 --- [           main] me.whiteship.autowired.DemoApplication   : No active profile set, falling back to default profiles: default
2020-03-16 13:33:24.073  INFO 14600 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2020-03-16 13:33:24.079  INFO 14600 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-03-16 13:33:24.079  INFO 14600 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.31]
2020-03-16 13:33:24.121  INFO 14600 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-03-16 13:33:24.121  INFO 14600 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 566 ms
// @PostConstruct가 출력되는 위치
class me.whiteship.autowired.MyBookRepository
2020-03-16 13:33:24.219  INFO 14600 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-03-16 13:33:24.342  INFO 14600 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2020-03-16 13:33:24.347  INFO 14600 --- [           main] me.whiteship.autowired.DemoApplication   : Started DemoApplication in 16.071 seconds (JVM running for 21.668)
// Runner가 출력되는 위치
  • Runner는 구동이 다 되었을 때 일을 한다.

  • 반면, @PostConstruct는 12. InitializingBean's afterPropertiesSet에 해당한다.

정리

  1. 빈 팩토리가 BeanPostProcessor 타입의 빈을 찾는다.

  2. 그 중 하나인 AutowiredAnnotationBeanPostProcessor를 찾는다.

  3. AutowiredAnnotationBeanPostProcessor가 일반적인 빈들에게 beanPostProcessor를 적용한다.

@Component
public class BookServiceRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        AutowiredAnnotationBeanPostProcessor bean
                = applicationContext.getBean(AutowiredAnnotationBeanPostProcessor.class);
        System.out.println(bean);
    }
}

Runner를 이용해 빈이 등록되어 있는지 확인할 수 있다.

PreviousApplicationContext와 빈 설정Next@Component와 컴포넌트 스캔

Last updated 2 years ago

Was this helpful?