Bean Lite Mode는 무엇인가요

kkambbak1·2023년 12월 29일
0

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Bean.html

Bean 어노테이션과 @Configuration

스프링 공식문서에서 가져온 Bean과 Configuration의 내용들이다.

@Bean Methods in @Configuration Classes

Typically, @Bean methods are declared within @Configuration classes. In this case, bean methods may reference other @Bean methods in the same class by calling them directly. This ensures that references between beans are strongly typed and navigable. Such so-called 'inter-bean references' are guaranteed to respect scoping and AOP semantics, just like getBean() lookups would. These are the semantics known from the original 'Spring JavaConfig' project which require CGLIB subclassing of each such configuration class at runtime. As a consequence, @Configuration classes and their factory methods must not be marked as final or private in this mode.

 @Configuration
 public class AppConfig {

     @Bean
     public FooService fooService() {
         return new FooService(fooRepository());
     }

     @Bean
     public FooRepository fooRepository() {
         return new JdbcFooRepository(dataSource());
     }

     // ...
 }

@Bean Lite Mode

@Bean methods may also be declared within classes that are not annotated with @Configuration. If a bean method is declared on a bean that is not annotated with @Configuration it is processed in a so-called 'lite' mode.

Bean methods in lite mode will be treated as plain factory methods by the container (similar to factory-method declarations in XML), with scoping and lifecycle callbacks properly applied. The containing class remains unmodified in this case, and there are no unusual constraints for the containing class or the factory methods.

In contrast to the semantics for bean methods in @Configuration classes, 'inter-bean references' are not supported in lite mode. Instead, when one @Bean-method invokes another @Bean-method in lite mode, the invocation is a standard Java method invocation; Spring does not intercept the invocation via a CGLIB proxy. This is analogous to inter-@Transactional method calls where in proxy mode, Spring does not intercept the invocation — Spring does so only in AspectJ mode.

@Component
 public class Calculator {
     public int sum(int a, int b) {
         return a+b;
     }

     @Bean
     public MyBean myBean() {
         return new MyBean();
     }
 }

무슨말이야?

@Configuration 안의 Bean 메서드

일반적으로 @Bean 메서드는 @Configuration 클래스 내에서 선언됩니다. 이 경우 Bean 메서드는 동일한 클래스의 다른 @Bean 메서드를 직접 호출하여 참조할 수 있습니다. 이를 통해 Bean 간의 참조가 강력하게 타이핑되고 탐색 가능하게 됩니다.

'inter-bean references' (Bean 사이의 참조)는 스코핑 및 AOP 시맨틱스를 존중하도록 보장됩니다.
이러한 시맨틱스는 런타임에 이러한 각 구성 클래스의 CGLIB 서브클래스를 필요로 하는 원래의 'Spring JavaConfig' 프로젝트에서 알려진 시맨틱스입니다.

결과적으로 이 모드에서는 @Configuration 클래스 및 해당 팩토리 메서드가 final 또는 private이어서는 안 됩니다

lite mode

@Bean 메서드는 @Configuration을 사용하지 않은 클래스(Bean)내에서도 선언될 수 있다.
이때 'lite' 모드로 처리된다.

lite mode의 Bean 메서드는 컨테이너에 의해 일반적인 팩토리 메서드로 취급될 것이며, 스코핑과 라이프사이클 콜백이 적절히 적용된다.

@Configuration이 있을 때와 달리, 'inter-bean-references'는 지원되지 않는다. 대신 하나의 @Bean-method가 다른 @Bean-method를 라이트 모드에서 호출할 때, 호출은 표준 자바 메서드 호출이며, 스프링은 CGLIB 프록시로 호출을 가로채지 않는다. 이는 프록시모드에서 스프링이 가로채지 못하는 inter-@Transactional과 유사하다. -- 스프링은 AspectJ 모드에서만 호출을 수행한다.

@Configuration 이 없다면 "lite" 모드로 처리된다.

https://easthshin.tistory.com/10

@Configuration 이 붙은 클래스와 다르게 lite모드에서는 @Bean 메서드가 bean간의 의존성을 선언할 수 없다. 예를 들어보자

@Configuration
public class AuthenticationPrincipalConfig {

    @Bean
    public SharedDependency sharedDependency() {
    	return new SharedDependency();
    }
    
    @Bean
    public AuthService authService() {
        return new AuthService(sharedDependency());
    }
    
    @Bean
    public AuthService2 authService2() {
        return new AuthService2(sharedDependency());
    }
}

위의 코드에서 sharedDependency() 를 authService 와 authService2 에서 호출하고 있다.

@Configuration 이 붙은 full mode 설정 클래스에서는 CGLIB 을 이용해 프록시 객체를 생성한다. 메서드를 호출했을 때 빈이 이미 생성되어 있다면 새로운 빈을 생성하지 않고 캐싱된 빈을 불러온다. 따라서, 스프링 빈 스코프가 싱글톤으로 설정되어 있다면 sharedDependency는 여러번 호출되지만, 스프링이 단 하나의 인스턴스만 생성하도록 보장한다.

public class AuthenticationPrincipalConfig {

	@Bean 
	public SharedDependency sharedDependency() { 
		return new SharedDependency(); 
	}
	
	@Bean 
	public AuthService authService() {
		return new AuthService(sharedDependency()); 
	}
	
	@Bean 
	public AuthService2 authService2() { 
		return new AuthService2(sharedDependency()); 
	} 
}

하지만 위와 같이 클래스에 @Configuration이 없는 순수한 클래스이거나, @Component 가 붙은 클래스라면 sharedDependency를 호출할 때 마다 인스턴스를 새로 생성한다. lite 모드에서는 프록시 객체를 생성하지 않고 바로 객체를 생성해버리기 때문이다. 즉, 빈 스코프가 싱글톤으로 설정되어 있으나 스프링이 싱글톤을 보장해주지 못한다.

lite mode로 작동하여 매번 다른 객체를 반환해 줄 수 있다.

참고로 ApplicationContext를 사용해서 설정 파일 가지고 빈을 수동 등록한다면, @Component가 없어도 Bean Lite Mode가 동작한다.

https://steady-coding.tistory.com/594#Bean_Lite_Mode

profile
윤성

0개의 댓글