Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does ApplicationContextAware work in Spring?

Tags:

java

spring

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.

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".

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

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

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

like image 254
Jimmy Avatar asked Feb 04 '14 12:02

Jimmy


People also ask

What is the use of an ApplicationContextAware interface?

Interface ApplicationContextAware. Interface to be implemented by any object that wishes to be notified of the ApplicationContext that it runs in. Implementing this interface makes sense for example when an object requires access to a set of collaborating beans.

What is the role of ApplicationContextAware in Spring to perform dependency injection to make bean aware on the container?

ApplicationContext represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the aforementioned beans. The container gets its instructions on what objects to instantiate, configure, and assemble by reading configuration metadata.

What is the use of BeanNameAware interface in Spring?

BeanNameAware makes the object aware of the bean name defined in the container. The beanName property represents the bean id registered in the Spring container. In our implementation, we're simply displaying the bean name.

What is the method we have to override when we are implementing ApplicationContextAware?

To create ApplicationContext aware bean, the class needs to implement ApplicationContextAware interfaceand override setApplicationContext() method. The ApplicationContextAware is used for bean lookup purpose and for those objects which needs to access file resources.


2 Answers

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

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:

@Inject // or @Autowired private ApplicationContext ctx; 
like image 53
Bozho Avatar answered Sep 24 '22 23:09

Bozho


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

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

enter this method,beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); will add ApplicationContextAwareProcessor to 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 applyBeanPostProcessorsBeforeInitialization to implement the bean post process. the process include inject the 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 ApplicationContextAwareProcessor that added before.

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);             }         }     } 
like image 25
Edward Avatar answered Sep 24 '22 23:09

Edward