-
Annotation 이 설정된 Beans 의 Scan 과 추가 Bean Register 위한 배경 지식Spring/Framework 2023. 9. 16. 16:59
AOP 로, Spring Beans 에서 필요한 bean 을 scan 하고, 추가로 bean 을 등록하기 위해 필요한 배경 지식들 입니다
BeanDefinitionRegistrar 관련
Spring ImportBeanDefinitionRegistrar
Spring ImportBeanDefinitionRegistrar는 Spring 애플리케이션 컨텍스트에 추가 BeanDefinition을 등록하는 데 사용되는 인터페이스입니다.
이 인터페이스를 구현하면 @Import 애노테이션을 사용하여 Spring 애플리케이션 컨텍스트에서 추가 BeanDefinition을 등록할 수 있습니다.
ImportBeanDefinitionRegistrar 인터페이스는 다음과 같은 두 가지 메서드를 제공합니다.
- registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry): Spring 애플리케이션 컨텍스트에 추가 BeanDefinition을 등록하는 메서드입니다.
- postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry): Spring 애플리케이션 컨텍스트에 등록된 BeanDefinition을 수정하는 메서드입니다.
ImportBeanDefinitionRegistrar 인터페이스를 구현하여 Spring 애플리케이션 컨텍스트에 추가 BeanDefinition을 등록하는 방법은 다음과 같습니다.
@Configuration public class MyConfiguration { @Bean public MyImportBeanDefinitionRegistrar myImportBeanDefinitionRegistrar() { return new MyImportBeanDefinitionRegistrar(); } } class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) { // BeanDefinition을 등록합니다. registry.registerBeanDefinition("myBean", BeanDefinitionBuilder.genericBeanDefinition(MyBean.class).getBeanDefinition()); } }
Spring의 BeanDefinitionRegistry
Spring의 BeanDefinitionRegistry는 Spring 애플리케이션 컨텍스트에 등록된 BeanDefinition을 저장하는 인터페이스입니다.
BeanDefinition은 Spring 애플리케이션 컨텍스트에서 관리되는 객체에 대한 정보를 나타냅니다.
BeanDefinitionRegistry 인터페이스를 구현하는 클래스는 다음과 같습니다.
- AbstractBeanDefinitionRegistry: BeanDefinitionRegistry 인터페이스의 기본 구현 클래스입니다.
- DefaultListableBeanFactory: BeanDefinitionRegistry 인터페이스를 구현하는 클래스 중 가장 많이 사용되는 클래스입니다.
- XmlBeanDefinitionReader: XML 파일에서 BeanDefinition을 읽어오는 클래스입니다.
BeanDefinitionRegistry 인터페이스는 다음과 같은 메서드를 제공합니다.
- registerBeanDefinition(String beanName, BeanDefinition beanDefinition): 지정된 이름과 BeanDefinition을 사용하여 BeanDefinition을 등록합니다.
- getBeanDefinition(String beanName): 지정된 이름의 BeanDefinition을 가져옵니다.
- getBeanNamesForType(Class<?> type): 지정된 타입의 모든 BeanDefinition의 이름을 가져옵니다.
- getBeanNamesForAnnotation(Class<? extends Annotation> annotation): 지정된 애노테이션이 적용된 모든 BeanDefinition의 이름을 가져옵니다.
- removeBeanDefinition(String beanName): 지정된 이름의 BeanDefinition을 제거합니다.
BeanDefinitionRegistry 인터페이스를 사용하여 Spring 애플리케이션 컨텍스트에 BeanDefinition을 등록하는 방법은 다음과 같습니다.
import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class BeanDefinitionRegistryExample implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { registry.registerBeanDefinition("testBean", new org.springframework.beans.factory.support.RootBeanDefinition(TestBean.class)); } @Bean public TestBean testBean() { return new TestBean(); } public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanDefinitionRegistryExample.class); TestBean testBean = context.getBean("testBean", TestBean.class); System.out.println(testBean); } }
위 예제에서는 BeanDefinitionRegistry를 구현한 BeanDefinitionRegistryExample 클래스를 작성하였습니다.
이 클래스는 postProcessBeanDefinitionRegistry() 메서드를 구현하여 스프링 빈의 등록 정보를 저장하고, testBean() 메서드를 구현하여 스프링 빈을 생성합니다.
이 클래스를 스프링 빈으로 등록하고, 다음과 같이 스프링 빈을 생성할 수 있습니다.
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanDefinitionRegistryExample.class); TestBean testBean = context.getBean("testBean", TestBean.class); System.out.println(testBean);
2nd 예제
import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class DynamicBeanRegistrationExample { public static void main(String[] args) { // 1. 애플리케이션 컨텍스트 생성 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); // 2. BeanDefinitionRegistry 얻기 BeanDefinitionRegistry registry = (BeanDefinitionRegistry) context.getBeanFactory(); // 3. 빈 정의 생성 및 등록 BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MyBean.class); builder.addPropertyReference("dependency", "anotherBean"); registry.registerBeanDefinition("myBean", builder.getBeanDefinition()); // 4. 애플리케이션 컨텍스트 초기화 context.refresh(); // 5. 빈 사용 MyBean myBean = context.getBean("myBean", MyBean.class); myBean.doSomething(); // 6. 애플리케이션 컨텍스트 종료 context.close(); } }
Environment
Spring EnvironmentAware
Spring EnvironmentAware는 Spring 애플리케이션 컨텍스트의 Environment 객체에 대한 참조를 제공하는 인터페이스입니다.
이 인터페이스를 구현하면 Spring 애플리케이션 컨텍스트에서 제공하는 환경 변수, 시스템 속성, 프로파일 정보를 사용할 수 있습니다.
EnvironmentAware 인터페이스는 다음과 같은 한 가지 메서드를 제공합니다.
- setEnvironment(Environment environment): Spring 애플리케이션 컨텍스트의 Environment 객체를 설정하는 메서드입니다.
EnvironmentAware 인터페이스를 구현하여 Spring 애플리케이션 컨텍스트의 Environment 객체에 대한 참조를 얻는 방법은 다음과 같습니다.
@Component public class MyBean implements EnvironmentAware { private Environment environment; @Override public void setEnvironment(Environment environment) { this.environment = environment; } public String getMyProperty() { // 환경 변수에서 값을 가져옵니다. return environment.getProperty("my.property"); } }
Annotation 관련
AnnotationMetadata
Spring의 AnnotationMetadata는 클래스, 인터페이스 또는 메서드에 적용된 애노테이션에 대한 정보를 제공하는 인터페이스입니다.
AnnotationMetadata 인터페이스는 다음과 같은 메서드를 제공합니다.
- getAnnotationAttributes(Class<? extends Annotation> annotationType): 지정된 애노테이션 타입의 애노테이션의 속성 값을 가져옵니다.
- getAnnotation(Class<? extends Annotation> annotationType): 지정된 애노테이션 타입의 애노테이션을 가져옵니다.
- getAnnotations(): 클래스에 적용된 모든 애노테이션을 가져옵니다.
- getMetaAnnotationAttributes(Class<? extends Annotation> metaAnnotationType): 지정된 메타 애노테이션 타입의 애노테이션의 속성 값을 가져옵니다. 주로 이 메소드 사용하기 위해 사용
- getMetaAnnotation(Class<? extends Annotation> metaAnnotationType): 지정된 메타 애노테이션 타입의 애노테이션을 가져옵니다.
- getMetaAnnotations(): 클래스에 적용된 모든 메타 애노테이션을 가져옵니다.
AnnotationMetadata 인터페이스를 사용하여 클래스, 인터페이스 또는 메서드에 적용된 애노테이션에 대한 정보를 가져오는 방법은 다음과 같습니다.
import org.springframework.core.annotation.AnnotationMetadata; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.SimpleMetadataReaderFactory; public class AnnotationMetadataExample { public static void main(String[] args) throws Exception { // MetadataReader를 생성합니다. MetadataReader metadataReader = new SimpleMetadataReaderFactory().getMetadataReader(MyBean.class.getName()); // AnnotationMetadata를 가져옵니다. AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); // 애노테이션의 속성 값을 가져옵니다. Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(MyAnnotation.class); String value = attributes.get("value").toString(); // 애노테이션을 가져옵니다. MyAnnotation myAnnotation = annotationMetadata.getAnnotation(MyAnnotation.class); // 메타 애노테이션의 속성 값을 가져옵니다. Map<String, Object> metaAttributes = annotationMetadata.getMetaAnnotationAttributes(Component.class); String annotationClass = metaAttributes.get("annotationClass").toString(); // 메타 애노테이션을 가져옵니다. Component component = annotationMetadata.getMetaAnnotation(Component.class); } } @MyAnnotation(value = "Hello, World!") @Component class MyBean { }
2nd 예제
import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.StandardAnnotationMetadata; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.stereotype.Component; @Component("myBean") public class MyBean { public static void main(String[] args) { // 클래스의 AnnotationMetadata를 생성 AnnotationMetadata metadata = new StandardAnnotationMetadata(MyBean.class); // 클래스에 부여된 어노테이션 확인 boolean isComponent = metadata.hasAnnotation(Component.class.getName()); System.out.println("Is @Component annotated: " + isComponent); // 클래스에 부여된 어노테이션의 속성 확인 AnnotationAttributes componentAttributes = metadata.getAnnotationAttributes(Component.class.getName()); String value = (String) componentAttributes.get("value"); System.out.println("@Component value attribute: " + value); } }
제목2
1
'Spring > Framework' 카테고리의 다른 글
References - Spring boot 3 - Problem Details for HTTP APIs (0) 2023.11.05 baeldung - spring boot 3 new (0) 2023.10.11 Next-Generation Cloud Native Apps with Spring Boot 3 • Thomas Vitale • GOTO 2023 - 세미나 리뷰 ( 작성중 ) (0) 2023.09.05 Spring Boot 3.1.0 (0) 2023.06.26 Bootiful Spring Boot 3 by Josh Long - demo 해보기 (0) 2023.06.24