Spring
[Spring] 자바 설정 빈 객체 생성 방법
재담
2022. 2. 10. 00:19
우선 다음 코드를 보자.
@Configuration
public class Config {
@Bean
public UserRepository userRepository() { ... }
@Bean
public PasswordChangeService pwChangeSvc() {
return new PasswordChangeService(userRepository());
}
@Bean
public AuthenticationService authenticationService() {
AuthenticationService authSvc = new AuthenticationService();
authSvc.setUserRepository(userRepository());
return authSvc;
}
// 이하 생략
...
}
자바 설정을 이용한 DI를 설명할 때 메서드를 여러 번 호출해도 실제로는 동일한 객체만 리턴된다고 했는데, 그 이유는 스프링이 설정 클래스를 상속받아 새로운 클래스를 만들어내기 때문이다. 예를 들어 위의 Config 클래스를 스프링 설정으로 사용할 경우, 스프링은 다음과 비슷한 방식으로 동작하는 하위 클래스를 생성한 뒤에 그 클래스를 이용해서 설정 정보를 사용한다.
public class SpringGenConfig extends Config {
private UserRepository userRepository;
@Override
public UserRepository userRepository() {
if (userRepository == null) {
userRepository = super.userRepository();
}
return userRepository;
}
// 다른 @Bean 메서드들도 비슷하게 재정의
...
}
위 코드에서 userRepository() 메서드는 상위 클래스에 정의된 userRepository() 메서드를 재정의하고 있는데, userRepository 필드가 null 이면 상위 클래스의 userRepository() 메서드를 호출해서 userRepository 필드에 할당하고 리턴한다. 따라서 userRepository() 메서드가 여러 번 호출되더라도 userRepository 필드에 할당된 동일한 객체를 리턴하게 된다.
실제 스프링은 하위 클래스를 생성할 때 CGLIB라는 도구를 이용해서 런타임에 하위 클래스를 생성한다. 하위 클래스를 만들고 메서드를 재정의하기 때문에, @Configuration 클래스와 @Bean 메서드는 final이면 안 된다. 또한 @Bean 메서드는 하위 클래스에서 재정의 할 수 있도록 하기 때문에 private이면 안 된다.