web-dev-qa-db-fra.com

Comment ApplicationContextAware fonctionne-t-il au printemps?

Au printemps, si un bean implémente ApplicationContextAware, il est alors en mesure d'accéder à applicationContext. Par conséquent, il est capable d'obtenir d'autres haricots. par exemple.

public class SpringContextUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext;     

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

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

Alors SpringContextUtil.getApplicationContext.getBean("name") peut obtenir le "nom" du haricot.

Pour ce faire, nous devrions placer ceci SpringContextUtil dans le applications.xml, Par exemple.

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

Ici le bean SpringContextUtil n'inclut pas la propriété applicationContext. J'imagine que lorsque le haricot printanier s'initialise, cette propriété est définie. Mais comment est-ce que c'est fait? Comment la méthode setApplicationContext est-elle appelée?

67
Jimmy

Lorsque le printemps instancie des haricots, il recherche quelques interfaces comme ApplicationContextAware et InitializingBean. Si elles sont trouvées, les méthodes sont appelées. Par exemple. (très simplifié)

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

Notez que dans les versions plus récentes, il peut être préférable d’utiliser des annotations plutôt que de mettre en œuvre des interfaces spécifiques à un ressort. Maintenant, vous pouvez simplement utiliser:

@Inject // or @Autowired
private ApplicationContext ctx;
79
Bozho

code source Spring pour expliquer le fonctionnement de ApplicationContextAware
lorsque vous utilisez ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Dans AbstractApplicationContext class, la méthode refresh() a le code suivant:

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

entrez cette méthode, beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); ajoutera 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));
...........

Lorsque spring initialise le bean dans AbstractAutowireCapableBeanFactory, dans la méthode initializeBean, appelez applyBeanPostProcessorsBeforeInitialization pour implémenter le post-traitement du bean. le processus comprend l'injection de l'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;
    }

lorsque BeanPostProcessor implémente Object pour exécuter la méthode postProcessBeforeInitialization, par exemple ApplicationContextAwareProcessor ajouté précédemment.

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);
            }
        }
    }
5
Edward