【SpringCooking】厨师就位(三)refresh方法之prepareBeanFactory()

1. 背景介绍

在上一篇文章【Spring Cooking】厨师就位(二)AnnotatedBeanDefinitionReader注册配置类 中,介绍了 AnnotatedBeanDefinitionReader 是如何注册配置类的 BeanDefinition 。此时整个容器依然还处于就绪阶段,厨师还在途中。本篇文章继续沿着注解开发的入口,开始探索十分重要的 refresh() 方法。

其中

postProcessBeanFactory(beanFactory)
onRefresh()

是空方法,留给子类去覆写。对于 AnnotationConfigApplicationContext,对于上述两个方法都没有覆写。

本篇着重讲解 refresh() 中的 prepareBeanFactory()。见名知其意,准备 BeanFactory,那是谁去准备这个 BeanFactory呢?其实就是 ApplicationContext。此方法主要就是配置 factory 的标准 context 特性,像 context class loader 和 post processor

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {

	public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
		this();
		register(componentClasses);
		refresh();
	}
}
public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
		
	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

			// 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);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
				contextRefresh.end();
			}
		}
	}
}

2. 学习目标

  1. 了解 prepareBeanFactory() 做了什么工作
  2. 了解每个注册组件的功能

3. 关键问题

4. 源码追踪

prepareBeanFactory()

  1. beanFactory.setBeanClassLoader(getClassLoader())
    配置 beanFactory 的类加载器,此类加载器从 ApplicationContext 获取

  2. beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()))
    配置Spring EL表达式解释器 StandardBeanExpressionResolver,主要用于解析spel表达式(#{}),注意与环境变量占位符区分(${})

    关于 StandardBeanExpressionResolver 如何去解析 spel 表达式,可参考另一篇文章 【SpringCooking】Spring组件库之StandardBeanExpressionResolver

  3. beanFactory.addPropertyEditorRegistrar()
    配置 PropertyEditorRegistrar,用于注册 PropertyEditor,关于 PropertyEditor 参照另一篇文章 【SpringCooking】Spring组件库之PropertyEditor

  4. beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this))
    添加 BeanPostProcessor - ApplicationContextAwareProcessor,这是一个很重要的 BeanPostProcessor,为实现了xxx_Aware接口的 Bean 注入各种上下文对象

  5. beanFactory.ignoreDependencyInterface()
    忽略 Aware 接口的依赖,也就是某个类自动注入 xxx_Aware 时不会起作用。这与上一步对应起来,就是只能通过 ApplicationContextAwareProcessor 去处理 Aware 接口的依赖

  6. beanFactory.registerResolvableDependency(Class<?> dependencyType, @Nullable Object autowiredValue)
    注册特定依赖类型的自动注入值,简单来说就是,当需要注入 dependencyType 时,会以 autowiredValue 来注入。这里注册了四种特定依赖类型的自动注入值

    • BeanFactory.class, beanFactory
    • ResourceLoader.class, this
    • ApplicationEventPublisher.class, this
    • ApplicationContext.class, this

    其中 beanFactory 为 DefaultListableBeanFactory,this 为 AnnotationConfigApplicationContext

    当我们需要依赖上述四种类型时,可以直接注入

    @Autowired
    private ApplicationContext context;
    
    @Autowired
    private BeanFactory beanFactory;
    
    @Autowired
    private ApplicationEventPublisher publisher;
    
    @Autowired
    private ResourceLoader resourceLoader;
    
  7. beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this))
    添加 BeanPostProcessor - ApplicationListenerDetector,检测实现了 ApplicationListener 的 bean 。它可以捕获到到 getBeanNamesForType 无法检测到的bean以及仅针对顶级bean工作的相关操作

  8. beanFactory.registerSingleton()
    注册了四个 bean,分别是

    systemProperties - 系统属性变量
    systemEnvironment - 系统环境变量
    environment - 包含前两者
    applicationStartup

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
		
	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Tell the internal bean factory to use the context's class loader etc.
		beanFactory.setBeanClassLoader(getClassLoader());
		if (!shouldIgnoreSpel) {
			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);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);

		// BeanFactory interface not registered as resolvable type in a plain factory.
		// MessageSource registered (and found for autowiring) as a bean.
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

		// Register early post-processor for detecting inner beans as ApplicationListeners.
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// Detect a LoadTimeWeaver and prepare for weaving, if found.
		if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// Set a temporary ClassLoader for type matching.
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}

		// Register default environment beans.
		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
		if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
			beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
		}
	}
}

ApplicationContextAwareProcessor

主要处理实现了 xxx_Aware 接口的 Bean,调用 setter 方法注入对应依赖

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(Object bean, String beanName) throws BeansException {
		if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
				bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
				bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
				bean instanceof ApplicationStartupAware)) {
			return bean;
		}

		AccessControlContext acc = null;

		if (System.getSecurityManager() != null) {
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		}

		if (acc != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareInterfaces(bean);
				return null;
			}, acc);
		}
		else {
			invokeAwareInterfaces(bean);
		}

		return bean;
	}

	private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof EnvironmentAware) {
			((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
		}
		if (bean instanceof EmbeddedValueResolverAware) {
			((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
		}
		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 ApplicationStartupAware) {
			((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
		}
		if (bean instanceof ApplicationContextAware) {
			((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
		}
	}

}

EmbeddedValueResolver

用于处理占位符和表达式

public class EmbeddedValueResolver implements StringValueResolver {
	
	private final BeanExpressionContext exprContext;

	@Nullable
	private final BeanExpressionResolver exprResolver;


	public EmbeddedValueResolver(ConfigurableBeanFactory beanFactory) {
		this.exprContext = new BeanExpressionContext(beanFactory, null);
		this.exprResolver = beanFactory.getBeanExpressionResolver();
	}
}

ApplicationListenerDetector

BeanPostProcessor that detects beans which implement the ApplicationListener interface. This catches beans that can’t reliably be detected by getBeanNamesForType and related operations which only work against top-level beans.

With standard Java serialization, this post-processor won’t get serialized as part of DisposableBeanAdapter to begin with. However, with alternative serialization mechanisms, DisposableBeanAdapter.writeReplace might not get used at all, so we defensively mark this post-processor’s field state as transient.

这是一个 BeanPostProcessor ,同于检测实现 ApplicationListener 接口的 bean,并将其添加到 ApplicationContext,实际是往 ApplicationContext 的 applicationEventMulticaster 添加 ApplicationListener

applicationEventMulticaster 会在 refresh() 方法的 initApplicationEventMulticaster() 进行初始化,ApplicationListener 会在 refresh() 方法的 registerListener() 进行注册,具体可参考 【SpringCooking】厨师就位(六)refresh方法之initApplicationEventMulticaster()

class ApplicationListenerDetector implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor {

	private static final Log logger = LogFactory.getLog(ApplicationListenerDetector.class);

	private final transient AbstractApplicationContext applicationContext;

	private final transient Map<String, Boolean> singletonNames = new ConcurrentHashMap<>(256);


	public ApplicationListenerDetector(AbstractApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
	}


	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		if (ApplicationListener.class.isAssignableFrom(beanType)) {
			this.singletonNames.put(beanName, beanDefinition.isSingleton());
		}
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) {
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		if (bean instanceof ApplicationListener) {
			// potentially not detected as a listener by getBeanNamesForType retrieval
			Boolean flag = this.singletonNames.get(beanName);
			if (Boolean.TRUE.equals(flag)) {
				// singleton bean (top-level or inner): register on the fly
				this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
			}
			else if (Boolean.FALSE.equals(flag)) {
				if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
					// inner bean with other scope - can't reliably process events
					logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +
							"but is not reachable for event multicasting by its containing ApplicationContext " +
							"because it does not have singleton scope. Only top-level listener beans are allowed " +
							"to be of non-singleton scope.");
				}
				this.singletonNames.remove(beanName);
			}
		}
		return bean;
	}

	@Override
	public void postProcessBeforeDestruction(Object bean, String beanName) {
		if (bean instanceof ApplicationListener) {
			try {
				ApplicationEventMulticaster multicaster = this.applicationContext.getApplicationEventMulticaster();
				multicaster.removeApplicationListener((ApplicationListener<?>) bean);
				multicaster.removeApplicationListenerBean(beanName);
			}
			catch (IllegalStateException ex) {
				// ApplicationEventMulticaster not initialized yet - no need to remove a listener
			}
		}
	}

	@Override
	public boolean requiresDestruction(Object bean) {
		return (bean instanceof ApplicationListener);
	}


	@Override
	public boolean equals(@Nullable Object other) {
		return (this == other || (other instanceof ApplicationListenerDetector &&
				this.applicationContext == ((ApplicationListenerDetector) other).applicationContext));
	}

	@Override
	public int hashCode() {
		return ObjectUtils.nullSafeHashCode(this.applicationContext);
	}

}

5. 结论

  1. 了解 prepareBeanFactory() 做了什么工作

    跑完 prepareBeanFactory(),beanFactory 以下属性发生了变化
    beanClassLoader - 配置 classloader
    beanExpressionResolver - 配置 Spring EL表达式解析器
    propertyEditorRegistrars - 配置 propertyEditor 注册器
    ignoredDependencyInterfaces - 配置忽略的依赖接口,即注入这些接口时将被无视
    resolvableDependencies - 配置特定依赖类型的自动注入值,即注入这些接口时将直接注入给定的值
    beanPostProcessors - 添加两个 BeanPostProcessor
    manualSingletonNames - LinkedHashSet结构,储存手动注册组件的 beanName
    singletonObjects - ConcurrentHashMap结构,存储已注册的 beanName 和 bean实例
    registeredSingletons - LinkedHashSet结构,存储已注册的 beanName

  2. 了解每个注册组件的功能

    StandardBeanExpressionResolver - 处理spel表达式
    PropertyEditorRegistrar - 注册 PropertyEditor
    ApplicationContextAwareProcessor - 为实现 xxxAware 接口的 bean 注入 xxx 依赖
    ApplicationListenerDetector - 检测实现了 ApplicationListener 的 bean

6. 注意细节

7. 待研究

  1. ApplicationListenerDetector, ApplicationListener, ApplicationEventMulticaster 三者的关系

  2. 在 ApplicationListenerDetector 的注释中说到,它能捕获到一些 Bean,这些 Bean 如果用仅针对 top-level bean 方法不能可靠地检测出来,如 getBeanNamesForType() 或者相关的操作。

    This catches beans that can’t reliably be detected by getBeanNamesForType and related operations which only work against top-level beans.

    查看 getBeanNamesForType() 方法,其在 ListableBeanFactory 接口下

    public interface ListableBeanFactory extends BeanFactory {
    	String[] getBeanNamesForType(ResolvableType type);
    	String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit);
    	String[] getBeanNamesForType(@Nullable Class<?> type);
    	String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
    	<T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException;
    	<T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException;
    }
    

    这些方法的注释都有一句加粗的NOTE

    NOTE: This method introspects top-level beans only. It does not check nested beans which might match the specified type as well.

    因此有必要了解 top-level beans 和 nested beans 是什么?是类与内部类的关系吗?
    这种不能检测的场景是什么?

8. 推荐文章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值