ApplicationContextAware는 Spring에서 어떻게 작동합니까?


82

봄에 빈이를 구현 ApplicationContextAware하면 applicationContext. 따라서 다른 콩을 얻을 수 있습니다. 예 :

public class SpringContextUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext;     

    public void setApplicationContext(ApplicationContext context) throws BeansException {
      applicationContext = context;
    }

    public static ApplicationContext getApplicationContext() {
      return applicationContext;
    }
}

그런 다음 SpringContextUtil.getApplicationContext.getBean("name")빈 "이름"을 얻을 수 있습니다.

이를 위해, 우리는이를 넣어해야 SpringContextUtil공진 영역 applications.xml, 예를 들어,

<bean class="com.util.SpringContextUtil" />

여기서 빈 SpringContextUtil은 속성을 포함하지 않습니다 applicationContext. 스프링 빈이 초기화되면이 속성이 설정되었다고 생각합니다. 그러나 이것은 어떻게 이루어 집니까? 메서드는 setApplicationContext어떻게 호출됩니까?


12
봄은 마법입니다. 마법 포용
로젠탈

답변:


98

스프링 빈을 인스턴스화 할 때, 같은 인터페이스의 몇 가지를 검색 ApplicationContextAware하고 InitializingBean. 발견되면 메소드가 호출됩니다. 예 (매우 단순화 됨)

Class<?> beanClass = beanDefinition.getClass();
Object bean = beanClass.newInstance();
if (bean instanceof ApplicationContextAware) {
    ((ApplicationContextAware) bean).setApplicationContext(ctx);
}

최신 버전에서는 스프링 관련 인터페이스를 구현하는 것보다 주석을 사용하는 것이 더 나을 수 있습니다. 이제 다음을 간단히 사용할 수 있습니다.

@Inject // or @Autowired
private ApplicationContext ctx;

4
대단히 감사합니다. 이것이 제가 원하는 것입니다! 스프링이 어떻게 작동하는지 이해하기 위해 스프링 코드를 읽어야 할 수도 있습니다.
Jimmy

2
대부분의 경우 @Autowired를 사용하는 것이 좋지만 작동하지 않을 수있는 다른 경우도 있습니다. 예를 들어 싱글 톤 인 "@Component"가 있지만 세션 범위가있는 빈을 삽입해야하는 경우입니다. 응용 프로그램 컨텍스트 생성에서 종속성이 자동 연결되므로 실제로 세션 빈이 삽입되지 않습니다. 응용 프로그램 컨텍스트에 대한 참조를 사용하면 세션 빈 인스턴스를 올바르게 반환하는 세션 빈을 프로그래밍 방식으로 검색 할 수 있습니다.
raspacorp

Spring이 대신 동적으로 생성 된 프록시 클래스를 주입 할 것으로 예상합니다. 이러한 클래스에는 응용 프로그램 범위가 있지만 액세스 할 때 세션 범위 인스턴스에 위임하거나 현재 실행중인 스레드에 바인딩 된 요청이없는 예외를 throw합니다.
xorcus

@raspacorp sesson 스코프 빈을 주입 ApplicationContext에서 가져올 수 없으면 ApplicationContextAware instance둘 중 하나 에서 가져올 수 없습니다 . 때문에이 ApplicationContextAware instance같은에서 빈을 얻는 applicationContext하나의 주입으로 객체입니다.
Tiina

10

In class
를 사용할 때 ApplicationContextAware가 어떻게 작동하는지 설명하는 Spring 소스 코드 는 다음 코드를 가지고 있습니다. ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
AbstractApplicationContextrefresh()

// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);

이 메소드를 입력하면 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));ApplicationContextAwareProcessor가 AbstractrBeanFactory에 추가됩니다.

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // Tell the internal bean factory to use the context's class loader etc.
        beanFactory.setBeanClassLoader(getClassLoader());
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
        // Configure the bean factory with context callbacks.
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
...........

Spring에서 bean을 초기화하면 AbstractAutowireCapableBeanFactory메소드 에서 bean 포스트 프로세스를 구현하도록 initializeBean호출 applyBeanPostProcessorsBeforeInitialization합니다. 프로세스에는 applicationContext를 삽입하는 것이 포함됩니다.

@Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
            throws BeansException {
        Object result = existingBean;
        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            result = beanProcessor.postProcessBeforeInitialization(result, beanName);
            if (result == null) {
                return result;
            }
        }
        return result;
    }

BeanPostProcessor가 Object를 구현하여 postProcessBeforeInitialization 메소드를 실행할 때, 예를 들어 ApplicationContextAwareProcessor이전에 추가 한 것입니다.

private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof EnvironmentAware) {
                ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
            }
            if (bean instanceof EmbeddedValueResolverAware) {
                ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
                        new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
            }
            if (bean instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
            }
            if (bean instanceof ApplicationEventPublisherAware) {
                ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
            }
            if (bean instanceof MessageSourceAware) {
                ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
            }
            if (bean instanceof ApplicationContextAware) {
                ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
            }
        }
    }

0

실행되는 ApplicationContext의 알림을 받고자하는 모든 객체에 의해 구현 될 인터페이스입니다.

위의 내용은 Spring 문서 웹 사이트 https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ApplicationContextAware.html 에서 발췌했습니다 .

그래서 그 때 뭔가를하고 싶다면 Spring 컨테이너가 시작될 때 호출되는 것 같았다.

컨텍스트를 설정하는 방법이 하나뿐이므로 컨텍스트를 얻고 이미 컨텍스트에서 뭔가를 수행 할 것입니다.


-1

Spring 컨테이너 서비스를 호출 할 수있는 현재 애플리케이션 컨텍스트 인 ApplicationContextAware 인터페이스. 클래스의 아래 메소드에 의해 주입 된 현재 applicationContext 인스턴스를 얻을 수 있습니다.

public void setApplicationContext(ApplicationContext context) throws BeansException.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.