Spring创建Bean的过程Debug
点击上方蓝色字体,选择“标星公众号”
优质文章,第一时间送达
作者 | x1aoda1
来源 | urlify.cn/QzYFba
Spring流程Debug
1.1 Spring测试环境搭建
Spring模块概览,绿色是模块,Spring中八大模块,黑色表示该模块包含的jar包(组件)。例如我们想要用IOC容器,也就是绿色的CoreContainer,我们需要导入Beans,Core,Context,SpEL(spring-expression)四个包。
Test:测试相关
Core Container:IOC容器
AOP:面向切面编程
Aspects:切面
Instrumenttation:跟JDK关联,一般不用
Messaging:消息服务,一般不用
Data Access/Integration:数据访问与集成(JDBC访问,Transaction事务,ORM对象关系映射,OXM和XML映射一般不用,JMS为Java消息服务Java-message-service一般不用)
Web:Web服务(WebSocket网络通信协议,Servlet, Web,Portlet一般不用)
最偷懒的方式,是直接导入Spring-Framework。但是可能导入不必要的包,导致项目打包后比较大
由于Spring-Content中的ApplicationContent是整个IOC的入口。我们导入Spring-context包即可
org.springframework
spring-context
5.2.3.RELEASE
我们导入spring-content后,默认会导入该组件的依赖jar,spring-content底层的依赖可以看到,实际上我们是导入了Core Container模块:
org.springframework
spring-aop
5.2.3.RELEASE
compile
org.springframework
spring-beans
5.2.3.RELEASE
compile
org.springframework
spring-core
5.2.3.RELEASE
compile
org.springframework
spring-expression
5.2.3.RELEASE
compile
新建Spring配置文件spring.xml:
"1.0" encoding="UTF-8"?>
"http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
"hello" class="com.xiaodai.service.Hello">
"id" value="1">
"name" value="zhangsan">
"age" value="18">
编写测试类:
import com.xiaodai.service.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
Hello hello = applicationContext.getBean("hello", Hello.class);
System.out.println(hello.getName());
}
}
1.2 Debug容器创建过程
从测试类的new ClassPathXmlApplicationContext("spring.xml")开始debug,进入ClassPathXmlApplicationContext,可以看到:
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
// 设置配置文件路径
setConfigLocations(configLocations);
if (refresh) {
// 核心步骤
refresh();
}
}
加载配置文件后,进入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.
/**
* 获得一个刷新的bean容器,实质就是获取工厂。
* 加载xml等配置文件,用该文件产生的BeanDefinition来创建一个工厂
**/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
/**
* 准备bean工厂
**/
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 后置增强,方便扩展
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 实例化并且执行BeanFactoryPostProcessors
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 实例化并且注册所有的BeanPostProcessor
registerBeanPostProcessors(beanFactory);
// 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();
}
}
}
1.3 AbstractApplicationContext的refresh()包含的13个方法分析
结合概览图一个一个方法分析:
方法1:prepareRefresh() => 准备工作
准备刷新,做一些最基本的准备化工作
protected void prepareRefresh() {
// Switch to active.
// 设置开始时间
this.startupDate = System.currentTimeMillis();
// 关闭状态设置为false
this.closed.set(false);
// 活跃状态设置为true
this.active.set(true);
// 打印日志
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// Initialize any placeholder property sources in the context environment.
// 初始化属性资源
initPropertySources();
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
// 获取环境信息,验证属性信息
getEnvironment().validateRequiredProperties();
// Store pre-refresh
// 存储预刷新的一些应用信息的监听器
ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
// 创建一些监听器事件的集合
this.earlyApplicationEvents = new LinkedHashSet<>();
}
总结:1.设置启动事件 2.设置关闭活跃的状态 3.获取环境对象并设置属性值 4.设置监听器以及需要发布事件的集合
重要的点:
获取环境信息,验证属性信息,getEnvironment().validateRequiredProperties();
存储预刷新的一些应用信息的监听器,在Spring中是空实现,但是SpringBoot中,是有具体的值的
方法2:obtainFreshBeanFactory() => 获得一个刷新的bean容器
获得一个刷新的bean容器,实质就是获取工厂。创建容器对象DefaultListableBeanFactory;加载xml配置文件的属性到当前的工厂中,最重要的就是BeanDefinition
AbstractRefreshableApplicationContext:
// 只要进到这个方法,那么我们创建的一定是一个新的工厂
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
// 如果存在先销毁,后关闭
destroyBeans();
closeBeanFactory();
}
try {
// 创建bean工厂,这里使用的就是DefaultListableBeanFactory。此时创建的工厂里面的属性值都是默认值
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 序列化id
beanFactory.setSerializationId(getId());
// 设置一些属性值
customizeBeanFactory(beanFactory);
// 加载bean的定义属性值。该方法有很多重载,非常复杂,核心是do操作
// 完成配置文件或者配置类文件的加载
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
方法3:prepareBeanFactory(beanFactory) => 准备(初始化)Bean工厂
为方法2拿到的工厂,设置某些具体的值
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
// 为bean工厂设置类加载器
beanFactory.setBeanClassLoader(getClassLoader());
// 设置SPEL解析器
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
// 添加一个BeanPostProcessor
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 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添加一个BeanPostProcessor增强器
ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (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());
}
}
方法4:postProcessBeanFactory(beanFactory) => 后置增强Bean(扩展实现)
空方法,方便扩展
方法5:invokeBeanFactoryPostProcessors(beanFactory) => 执行BFPP
实例化并且执行BeanFactoryPostProcessors
/**
* Instantiate and invoke all registered BeanFactoryPostProcessor beans,
* respecting explicit order if given.
*
Must be called before singleton instantiation.
* 单例对象之前一定调用,因为单例bean创建后就只有一份
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
方法6:registerBeanPostProcessors(beanFactory) => 注册BPP
实例化并且注册所有的BeanPostProcessor。实例化Bean之前的准备工作
/**
* Instantiate and register all BeanPostProcessor beans,
* respecting explicit order if given.
*
Must be called before any instantiation of application beans.
*/
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
方法7:initMessageSource() => 国际化设置
方法8:initApplicationEventMulticaster() => 初始化应用程序的多波器和广播器
也属于准备工作
方法9:onRefresh() => 预留给子类做扩展
空方法
方法10:registerListeners() => 注册监听器
也属于准备工作
/**
* Add beans that implement ApplicationListener as listeners.
* Doesn't affect other listeners, which can be added without being beans.
*/
protected void registerListeners() {
// Register statically specified listeners first.
for (ApplicationListener listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
Set earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
方法11:finishBeanFactoryInitialization(beanFactory) => 实例化所有单例对象
面试常问,工作常用。过程比较复杂
/**
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
/**
* 把类型转化操作,设置到当前的beanFactory里面去
**/
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
/**
* 判断当前的beanFactory有没有内置的值处理器
**/
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
/**
* 织入Aware
**/
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
// 设置类加载器
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
/**
* 冻结:某些bean不需要进行修改操作了,放入
**/
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
/**
* 实例化所有非懒加载的实例对象(重要)
**/
beanFactory.preInstantiateSingletons();
}
实例化所有非懒加载的实例对象方法:
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
/**
* 拿到所有注册bean的名称
**/
List beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
// 循环去创建我们需要的单例对象
for (String beanName : beanNames) {
// 拿到bean的定义信息,就是我们在xml配置文件里面指定的一些属性
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 是否是抽象的,是否是单例的,是否是懒加载的
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 判断当前类是否实现了factoryBean接口。一般没实现,直接进入下面的getBean
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean factory = (FactoryBean) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction)
((SmartFactoryBean) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
// 通过beanName。拿到bean
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction