Reflection Bean

calis_ws·2024년 1월 3일
0

스프링 컨테이너는 Reflection 으로 생성된 Bean의 정보를 실행 이후에 어떻게 알 수 있을까?

Reflaction API란?
https://syongsyong2.tistory.com/96

스프링 컨테이너는 애플리케이션을 초기화하고 빈을 생성하는 과정에서 Reflection을 사용하여 빈의 정보를 수집하고 유지한다.

Reflection 으로 생성된 Bean의 정보를 알기 위한 방법

1. BeanDefinition

스프링에서 빈을 정의하는 메타데이터를 담고 있는 인터페이스이다. 이 객체는 빈의 클래스, 스코프, 생성자 및 프로퍼티 등의 정보를 포함한다.

public class BeanInfoExample {

    public static void main(String[] args) {
        // AnnotationConfigApplicationContext를 통해 컨텍스트를 생성
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();

        // 빈 등록을 위한 BeanFactory
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory();

        // 빈의 메타데이터를 정의하는 BeanDefinition 생성
        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(MyBean.class);

        // 빈을 등록
        beanFactory.registerBeanDefinition("myBean", beanDefinition);

        // 빈 이름으로 BeanDefinition 가져오기
        BeanDefinition myBeanDefinition = beanFactory.getBeanDefinition("myBean");

        // BeanDefinition에서 정보 추출
        String beanClassName = myBeanDefinition.getBeanClassName();
        String[] propertyNames = myBeanDefinition.getPropertyValues().getPropertyNames();

        // 빈의 정보 출력
        System.out.println("Bean Class Name: " + beanClassName);
        System.out.println("Bean Property Names: " + String.join(", ", propertyNames));

        // 컨텍스트 종료
        applicationContext.close();
    }

    // 간단한 빈 클래스 정의
    static class MyBean {
        private String name;

        public void setName(String name) {
            this.name = name;
        }
    }
}

2. ApplicationContext

Bean 을 관리하고 생성하는 주요 인터페이스 중 하나이며, 여러 메소드를 통해 빈의 메타데이터에 접근할 수 있다.

getBeanDefinitionNames() : 컨테이너에 등록된 모든 빈의 이름을 문자열 배열로 반환

getBeanDefinition(String beanName) : 지정된 빈의 BeanDefinition을 반환. BeanDefinition에는 빈의 클래스 타입, 스코프, 생성자 인자, 속성 등의 메타데이터가 포함된다.

getBean(String beanName) : 지정된 이름의 빈 인스턴스를 반환. 빈의 인스턴스를 얻으면 해당 객체의 클래스 타입 등을 통해 reflection을 사용하여 더 많은 정보를 얻을 수 있다.
// ApplicationContext 생성
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

// 등록된 모든 빈의 이름 얻기
String[] beanNames = context.getBeanDefinitionNames();

for (String beanName : beanNames) {
    // 각 빈의 BeanDefinition 얻기
    BeanDefinition beanDefinition = ((AbstractApplicationContext) context).getBeanFactory().getBeanDefinition(beanName);

    // BeanDefinition을 통한 메타데이터 활용
    String className = beanDefinition.getBeanClassName();
    ScopeMetadata scopeMetadata = beanDefinition.getScopeMetadata();
    
    // 클래스 정보 등을 통해 reflection으로 더 많은 정보 얻기
    Class<?> beanClass = Class.forName(className);
    
    // 원하는 작업 수행
    // ...
}

3. BeanPostProcessor

스프링 컨테이너에서 빈이 생성되거나 초기화 될 때 추가적인 작업을 수행할 수 있는 인터페이스이다. BeanPostProcessor는 빈이 초기화되기 전과 후에 콜백 메서드를 제공하며, 여기서 Reflection을 통해 빈의 정보를 확인하거나 수정할 수 있다.

public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 빈 초기화 전에 수행할 작업 (콜백 메서드)
        // 여기서 reflection을 통해 빈의 정보에 접근 가능
        System.out.println("Before Initialization - Bean Name: " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // 빈 초기화 후에 수행할 작업 (콜백 메서드)
        // 여기서 reflection을 통해 빈의 정보에 접근 가능
        System.out.println("After Initialization - Bean Name: " + beanName);
        return bean;
    }
}
@Configuration
public class AppConfig {
	// 컨테이너에 등록
    @Bean
    public MyBeanPostProcessor myBeanPostProcessor() {
        return new MyBeanPostProcessor();
    }

    // 다른 빈들을 정의
    // ...
}

정리

스프링은 애플리케이션이 실행되는 초기 단계에서 Reflection API를 사용하여 빈의 정보를 수집하고, 이 정보는 ApplicationContext를 통해 런타임에도 관리된다. 이를 통해 스프링 컨테이너는 위의 컴포넌트들을 활용하여 동적으로 생성된 빈의 상태를 추적하고 필요한 작업을 수행할 수 있다.

profile
반갑습니다람지

0개의 댓글