
객체 생성을 개발자가 직접 'new 객체'에서 생성/관리하지 않고, spring이 자동으로 해줬으면 좋겠어. 어떻게 할 수 있을까?
1) @Configuration, @Bean을 이용한 객체 의존성 주입
2) @ComponentScan, @Component, @Autowired를 통한 객체 의존성 주입
3) 예전방식인 xml
개괄적 설명
-- ApplicationContext이라는 객체 자동 생성/관리를 담당해주는 스프링 컨테이너에 spring이 관리하기 원하는 객체들을 전달해 주면돼. 어떻게????
원리
1) 클래스를 하나 만들어서 @Configurator을 해서 '이 클래스에서 bean(스프링 컨테이너에서 생성 관리하는 객체)를 만들거야'라고 선언하고
2) @Bean을 단 메소드를 만들어서, 메소드에서 원하는 객체를 만들어줘
3 그렇게 하면, 스프링 컨테이너가 애플리케이션 시작 시 이 설정 클래스를 읽고, @Bean 메소드에서 반환된 객체를 빈으로 등록해.
4) 그럼 이후에 실행 파일에서
4-1. 설정 클래스를 읽어와서 스프링 컨테이너를 초기화하고 빈을 생성해.
이 때 bean이 생성되는 원리는, 스프링 컨테이너가 초기화 되면서 @Bean으로 적은 method가 호출되는 거야.
ApplicationContext context
= new AnnotationConfigApplicationContext(AppConfig.class);
4-2.context.getBean() 메소드를 사용해서 생성된 빈을 가져오고 필요한 값을 불러오면 돼
// @ Configuration : Spring아, 이 class에서 니가 bean 자동으로 관리해줘야 할 bean(객체)들을 줄게.
// (나중에 app 실행 시 자동으로 @Configuration이 있는 클래스를 읽고 @bean에 있는 객체를 spring container로 전달해줌.)
@Configuration
public class AppConfig2 {
// @Bean : spring아, 내가 여기에 니가 관리해줘야 할 객체들 메소드 안에다가 넣어 줄게.
// 나중에 내가 AnnotationConfigApllicationContext 객체 만들면 그 때 니가 이 메소드 호출하면서 객체도 생성해줘
@Bean
GreetingServiceImpl methodForContainerCall() {
return new GreetingServiceImpl("미돌");
}
/* @Test :
- JUnit(자바 애플리케이션에서 단위 테스트를 작성하고 실행하는 데 널리 사용되는 테스트 프레임워크)의 애노테이션으로,
- 작동원리 :
1) JUnit 프레임 워크를 Spring의 dependency에 추가한다.
2) 코드 짤 때 @Test라는 Junit의 annotation를 붙이고
3) 그 바로 밑에 아무 이름으로나 method를 작성하고
4) 개발자가 play 버튼을 누르면 JUnit이 실행되면서 해당 메서드가 자동으로 호출된다.
*/
@Test
public void randomTest() {
//내가 다른 클래스 파일에서 @configuration @bean 사용해서 bean을 등록해놨거든?
// AnnotationConfigApplicationContenxt야, 그 클래스 불러오고 자동으로 @bean 붙은 메소드 생성해서 객체도 생성해줘.
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig2.class);
// 그럼 생성된 객체 중에서, 00 객체를 가져와줘.
GreetingServiceImpl midol = context.getBean(GreetingServiceImpl.class);
// 그럼 내가 생성된 객체로 뭔가를 테스트 해볼게
midol.getGreet();
}
}
1) @Component("닉네임")
- 설명 : 일단 내가 스프링 컨테이너에서 알아서 객체 생성 관리해줬으면 하는 클래스에, @Component를 붙여.
그럼 '이 객체는 spring에서 관리할거야'라고 공표하는 거야.
즉, 1번 방식의 @Bean와 같은 기능이지.
나중에 어플리케이션이 실행됨과 동시에 얘는 컨테이너에 객체가 등록이 될 거야.
참고로 이 때 ("닉네임")은 생략 가능해.
- 예시코드 :
// @Component : StudentController 객체의 생성 및 관리는 spring에 일임하겠다.
@Component
public class StudentController {
코드 구현...
}
2) @ComponentScan(basePackages = "프로젝트 내 @component 있는 경로")
: 클래스를 하나 생성해서, 클래스 위에 위의 코드를 붙여.
이렇게 함으로써 '나중에 내가 이 클래스를 특정 방식으로 부르면 해당 경로의 @component로 등록되어 있는 클래스를 bean으로 등록해줘' 라고 공표해.
3-1) @Autowired
- 설명 : spring이 자동 생성한 객체를 클래스 내에서 사용하고 싶을 때는,
자동 생성 객체가 포함된 메서드에 @Autowired를 적어주면 돼.
- 예시 코드 : 3-2의 예시코드 참고
3-2) @Qualifier("Component의 Nickname")
- 설명 : @Autowired 관련해서, 고모듈 클래스에서 저모듈 클래스에 의존할 때,
저모듈 클래스가 interface라면 @Autowired의 객체의 종류가 달라지는 경우도 있잖아?
이런 경우에는 @Qualifier를 써서 어떤 객체를 받을 건지 선택하면 돼.
- 예시 :
public StudentController(@Qualifier("memoryRepo") StudentRepository studentRepository) {
System.out.println("생성자 주입!");
this.studentRepository = studentRepository;
}
3-3) @Profile("Profile의 닉네임")
- 설명 : Spring에서 관리하는 객체의 생성자가
parameter로 여러 타입의 객체를 받을 수 있을 때, 그 중 하나만 받으려먼
1) 클래스 위에 @Component + @Profile 조합 쓰고
2) Resource폴더 -> Application.properties 파일에
spring.profiles.active = dev <- 이런 식으로 써서 선택도 가능

StudentController(StudentRepository studentRepo) {}), StudentRepository는 인터페이스이기 때문에 객체를 StudentDBRepository 객체 혹은 StudnetMemoryRepository 둘 중 하나를 받을 수 있다. 그런데 어떤 객체를 받을지 안 정해져 있다.StudentController(@Qualifier("DBRepo") StudentRepository studentRepo) {} 이런식으로 @Qualifier("받을 Component 객체 닉네임") 를 추가해서 어떤 객체를 받을 것일지 명시
1) Build 도구 dependencies에 lombok 라이브러리 추가
2) 위의 설정에 의해, 자바 컴파일러가 실행될 때 lombok의 annotation 처리기가 실행됨
3) -> lombook Aannotation(@) 처리기에 의해 getter 자동 생성됨
- FYI. Java SE ver. 16 이후로는 record로 클래스 생성하면 됨