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?
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.
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.
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.
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.
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;
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); } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With