ApplicationContextAware如何在Spring中运行?

Jim*_*mmy 72 java spring

在spring中,如果bean实现了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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后SpringContextUtil.getApplicationContext.getBean("name")可以获得bean"名称".

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

<bean class="com.util.SpringContextUtil" />
Run Code Online (Sandbox Code Playgroud)

这里的bean SpringContextUtil不包含属性applicationContext.我想当spring bean初始化时,会设置此属性.但这是怎么做到的?如何setApplicationContext调用该方法?

Boz*_*zho 84

当spring实例化bean时,它会查找像ApplicationContextAwareand 这样的几个接口InitializingBean.如果找到它们,则调用这些方法.例如(非常简化)

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

请注意,在较新的版本中,最好使用注释,而不是实现特定于Spring的接口.现在你可以简单地使用:

@Inject // or @Autowired
private ApplicationContext ctx;
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢,这就是我想要的!也许我需要阅读一些弹簧代码来了解弹簧是如何工作的. (3认同)
  • 最好在大多数情况下使用@Autowired,但有些情况可能不起作用,例如当你有一个"@Component"是一个单例,但你需要注入一个具有会话范围的bean.由于依赖项是在应用程序上下文创建中自动装配的,因此通过引用应用程序上下文,您不会真正注入会话bean,您可以以编程方式检索会话bean,这将正确返回会话Bean实例. (2认同)

Edw*_*ard 7

春源代码来解释如何了ApplicationContextAware工作
,当您使用ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
AbstractApplicationContext类的refresh()方法有以下代码:

// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
Run Code Online (Sandbox Code Playgroud)

输入此方法,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));
...........
Run Code Online (Sandbox Code Playgroud)

当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;
    }
Run Code Online (Sandbox Code Playgroud)

当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);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)