Java ApplicationContextAware 在 Spring 中是如何工作的?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21553120/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 09:20:51  来源:igfitidea点击:

How does ApplicationContextAware work in Spring?

javaspring

提问by Jimmy

In spring, if a bean implements ApplicationContextAware, then it is able to access the applicationContext. Therefore it is able to get other beans. e.g.

在 spring 中,如果 bean 实现了ApplicationContextAware,那么它就可以访问applicationContext. 因此它能够获取其他bean。例如

public class SpringContextUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext;     

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

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

Then SpringContextUtil.getApplicationContext.getBean("name")can get the bean "name".

然后SpringContextUtil.getApplicationContext.getBean("name")可以得到bean的“名称”。

To do this, we should put this SpringContextUtilinside the applications.xml, e.g.

要做到这一点,我们应该把它SpringContextUtil放在applications.xml,例如

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

Here the bean SpringContextUtildoesn't include the property applicationContext. I guess when spring bean initialize, this property is set. But how is this done? How does the method setApplicationContextget called?

这里的 beanSpringContextUtil不包括 property applicationContext。我猜当 spring bean 初始化时,这个属性被设置。但这是如何做到的?方法是如何setApplicationContext被调用的?

采纳答案by Bozho

When spring instantiates beans, it looks for a couple of interfaces like ApplicationContextAwareand InitializingBean. If they are found, the methods are invoked. E.g. (very simplified)

当 spring 实例化 bean 时,它会寻找几个接口,比如ApplicationContextAwareInitializingBean。如果找到它们,则调用这些方法。例如(非常简化)

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

Note that in newer version it may be better to use annotations, rather than implementing spring-specific interfaces. Now you can simply use:

请注意,在较新的版本中,最好使用注解,而不是实现特定于 spring 的接口。现在您可以简单地使用:

@Inject // or @Autowired
private ApplicationContext ctx;

回答by techiesantosh

ApplicationContextAware Interface ,the current application context, through which you can invoke the spring container services. We can get current applicationContext instance injected by below method in the class

ApplicationContextAware Interface,当前应用上下文,通过它可以调用spring容器服务。我们可以通过类中的以下方法获取当前的 applicationContext 实例

public void setApplicationContext(ApplicationContext context) throws BeansException.

回答by Edward

Spring source code to explain how ApplicationContextAware work
when you use ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
In AbstractApplicationContextclass,the refresh()method have the following code:

Spring源代码解释ApplicationContextAware在类中
使用时是如何工作的,方法有如下代码: ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
AbstractApplicationContextrefresh()

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

enter this method,beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));will add ApplicationContextAwareProcessor to AbstractrBeanFactory.

进入这个方法,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));
...........

When spring initialize bean in AbstractAutowireCapableBeanFactory, in method initializeBean,call applyBeanPostProcessorsBeforeInitializationto implement the bean post process. the process include inject the applicationContext.

spring在初始化bean时AbstractAutowireCapableBeanFactory,在方法中initializeBean,调用applyBeanPostProcessorsBeforeInitialization实现bean的post处理。该过程包括注入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;
    }

when BeanPostProcessor implement Objectto execute the postProcessBeforeInitialization method,for example ApplicationContextAwareProcessorthat added before.

当 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);
            }
        }
    }

回答by Yu Chai

Interface to be implemented by any object that wishes to be notified of the ApplicationContext that it runs in.

任何希望被通知它运行的 ApplicationContext 的对象要实现的接口。

above is excerpted from the Spring doc website https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ApplicationContextAware.html.

以上摘自 Spring doc 网站https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ApplicationContextAware.html

So, it seemed to be invoked when Spring container has started, if you want to do something at that time.

所以,它似乎是在 Spring 容器启动时调用的,如果你当时想做点什么。

It just has one method to set the context, so you will get the context and do something to sth now already in context I think.

它只有一种设置上下文的方法,因此您将获得上下文并在我认为现在已经在上下文中执行某些操作。