在Spring中,当一个bean实现了ApplicationContextAware接口,这个bean便可以获取到ApplicationContext对象,进而获取应用上下文中的bean。
package com.huawei.nlz.springplayground.applicationcontextaware;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringBeanFactory implements ApplicationContextAware {
private static ApplicationContext context;
/**
* 从Spring应用上下文中获取特定类型的bean
*
* @param c 类型的Class对象
* @param 类型
* @return bean
*/
public static T getBean(Class c) {
return context.getBean(c);
}
/**
* 从Spring应用上下文中获取指定名字的特定类型的bean
*
* @param name bean名字
* @param c 类型的Class对象
* @param 类型
* @return bean
*/
public static T getBean(String name, Class c) {
return context.getBean(name, c);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
}
这里的SpringBeanFactory被声明为要为之创建单例bean,然后在setApplicationContext回调中,把Spring传过来的ApplicationContext保存到自己内部的静态字段context上,然后将从context上获取bean封装为公共的静态方法开放给其他类调用。
一般的应用场景即是上面所示的bean的工厂。以上面的类为例,我们可以通过SpringBeanFactory.getBean("myBean", MyBean.class)来获取bean。这使得在一些无法注入的地方我们也可以获取到bean,比如Util类中,为我们带来极大的便利。
最后我们跟踪一下Spring的源码,看看具体是怎么执行的。
我们进入AbstractApplicationContext的refresh方法,
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
...
进入prepareBeanFactory,
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));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
...
可以看到Spring自动给添加上了一个BeanPostProcessor--ApplicationContextAwareProcessor,
我们看看ApplicationContextAwareProcessor,
class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ConfigurableApplicationContext applicationContext;
private final StringValueResolver embeddedValueResolver;
/**
* Create a new ApplicationContextAwareProcessor for the given context.
*/
public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
}
@Override
@Nullable
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
if (System.getSecurityManager() != null &&
(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction
ApplicationContextAwareProcessor确实实现了BeanPostProcessor接口,它会判断bean的类型,如果bean是ApplicationContextAware接口,那么就调用这个对象的setApplicationContext方法。
那么BeanPostProcessor是何时调用的呢?
其代码流程如下: AbstractApplicationContext.refresh -> AbstractApplicationContext.finishBeanFactoryInitialization -> ConfigurableListableBeanFactory(DefaultListableBeanFactory).preInstantiateSingletons -> DefaultListableBeanFactory.getBean -> DefaultListableBeanFactory.doGetBean -> DefaultListableBeanFactory.createBean -> AbstractAutowireCapableBeanFactory.doCreateBean -> AbstractAutowireCapableBeanFactory.initializeBean。
我们看下最末尾的AbstractAutowireCapableBeanFactory的initializeBean方法:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction
其中applyBeanPostProcessorsBeforeInitialization会对该bean对象应用所有的beanPostProcessors:
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
...
public List getBeanPostProcessors() {
return this.beanPostProcessors;
}