ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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

     

    댓글

Designed by Tistory.