Как ApplicationContextAware работает в Spring?

В spring, если bean реализует ApplicationContextAware, тогда он может получить доступ к applicationContext. Поэтому он может получить другой beans. например

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") может получить имя bean ".

Чтобы сделать это, мы должны поместить этот SpringContextUtil внутри applications.xml, например.

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

Здесь bean SpringContextUtil не включает свойство applicationContext. Я думаю, когда spring bean initialize, это свойство установлено. Но как это делается? Как вызывается метод setApplicationContext?

Ответ 1

Когда spring создает экземпляр beans, он ищет пару интерфейсов, таких как ApplicationContextAware и InitializingBean. Если они найдены, методы вызываются. Например. (очень упрощенный)

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

Обратите внимание, что в более новой версии лучше использовать аннотации, а не использовать spring -специфические интерфейсы. Теперь вы можете просто использовать:

@Inject // or @Autowired
private ApplicationContext ctx;

Ответ 2

Spring исходный код, чтобы объяснить, как работает ApplicationContextAware
когда вы используете ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
В классе AbstractApplicationContext метод refresh() имеет следующий код:

// 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 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, в методе initializeBean вызовите applyBeanPostProcessorsBeforeInitialization, чтобы реализовать процесс post bean. этот процесс включает в себя инъекцию 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);
            }
        }
    }

Ответ 3

Интерфейс ApplicationContextAware, текущий контекст приложения, через который вы можете вызвать службы контейнера spring. Мы можем получить текущий экземпляр applicationContext, введенный ниже методом в классе

    public void setApplicationContext(ApplicationContext context) throws BeansException.

Чтобы лучше понять, как использовать ApplicationContextAware, обратитесь к этому http://www.javapointer.com/spring/spring-core/how-to-use-applicationcontextaware-in-spring/