Spring完整的核心流程

核心方法refresh()

reresh()方法就是spring的最核心的方法,当你启动spring容器时就会调用到,里面涉及了核心的13个方法。囊括了spring的bean的生成,对循环依赖的解决,AOP的处理。
refresh()方法注释
Load or refresh the persistent representation of the configuration, which might an XML file, properties file, or relational database schema.
As this is a startup method, it should destroy already created singletons if it fails, to avoid dangling resources. In other words, after invocation of that method, either all or no singletons at all should be instantiated.
他是说这个refresh方法是用于加载或者刷新配置的持久性,可以是xml文件 或者properties文件 或者关系数据架构配置修改。这一点就是说如果你的配置文件发生改变你可以通过调用这方法让他重新加载。像一些动态刷新配置的一些技术,应该就是利用这个方法实现的。
这个启动方法,如果失败应该销毁已有的单例,避免资源悬空。该方法调用后,要么全部实例化,要么一个都不实例化,这有点事务的感觉。

prepareRefresh()

这个方法注释
Prepare this context for refreshing, setting its startup date and active flag as well as performing any initialization of property sources

加载的准备工作,记录下启动时间和一些标志位比如closed active这些标志,还有一些系统属性,配置文件的property的初始化等一些资源

obtainFreshBeanFactory()

获取beanfactory工厂,点击去可以看到一个refreshBeanFactory方法。这个方法创建了DefaultListableBeanFactory这个类型的beanFactory 翻译过来就是可以列表化的bean工厂,实质上abstractApplicationContext持有的bean工厂类型就是这个类型,作为spring的默认的工厂。
DefaultListableBeanFactory 可以注册删除和查询bean,他继承了AbstractAutowireCapableBeanFactory 提供了bean的实例化,属性填充,初始化和autowring自动注入。refreshBeanFactory方法还通过loadBeanDefinitions方法进行对bean定义信息的加载。

prepareBeanFactory(beanFactory)

传入上面得到DefaultListableBeanFactory 来进行关于beanFacoty的准备工作。

beanFactory.setBeanClassLoader(getClassLoader());  

相关注释: Tell the internal bean factory to use the context’s class loader
设置类加载器,告诉beanFactoty得使用当前applicationContext的类加载器

beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));

设置beanDefinition 定义信息的el表达式处理器 比如@Value("${book.name}") @Value("#{user}")

beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

设置资源编辑器的注册器 啥意思,看里面的ResourceEditorRegistrar 这个类是一个负责注册资源编辑器的的登记员,
通过查看ResourceEditor这个类的注释
Editor for Resource descriptors, to automatically convert String locations e.g. file:C:/myfile.txt or classpath:myfile.txt to Resource properties instead of using a String location property.
我们就得知而资源编辑器就是 把你配置的 file:C:/myfile 或者这种 classpath:myfile.txt 配置文件资源 ,或者网络资源等,把他们转变成真正的资源信息,而不是一个简单的字符串。这个代码就是把这些各种解析资源的东西给统统注册进来,以便后面使用。

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

配置各种回调函数 比如EnvironmentAware EmbeddedValueResolverAware ResourceLoaderAware ApplicationEventPublisherAware
MessageSourceAware ApplicationContextAware。
ApplicationContextAwareProcessor这个前置处理器的postProcessBeforeInitialization 方法当bean创建的时候会被调用到,然后就会去调用xxxaware的set方法。
ignoreDependencyInterface()看他的注释Ignore the given dependency interface for autowiring. 注意这个宾语是接口,忽悠这个接口的依赖注入,这类接口都有个特性都有个setXXX的方法,对于xml的注入,有2种一个是constuctor的注入,另一个就是set方式的注入,set方式是通过调用set方法进行注入的,我们这个走向是基于xml的;注解是另一种走向,他会无视这个,直接从bean容器去拿。但是我们这个ApplicationContextWare这类的接口本意就是通过容器调用set方法给你回调注入进去,所以他不允许你直接拿个你自己配置的ApplicationContext实例给自己注入。

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

这个方法的意思是事先把BeanFactory类型的实例注册进去,作为一个该类型默认的一个实例,因为beanFactory的实现可能会有很多种,需要明确具体用哪个,可以用registerResolvableDependency方法设置。

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

配置ApplicationListener的探测器,探测的方法就是利用BeanPostProcessor在bean创建的生命周期的实例化初始化完成后,调用postProcessAfterInitialization方法判断如果是属于ApplicationListener类型就记录到spring容器中,监听器的实现就是Observer的设计模式
在这里插入图片描述
把listener监听者就保存起来,等后面发通知的时候就去逐个去通知。不过spring的ApplicationListener做了过滤,所以你可以让指定类型的事件监听者得到该事件类型的通知。
并且ApplicationListenerDetector探测器在监听者bean销毁前得把这个监听者从监听者集合中移除,事实上发通知这个动作都是由ApplicationEventMulticaster 这个事件的多播器来处理的,可以查阅ApplicationContext.publishEvent方法得知。
在这里插入图片描述
LoadTimeWeaving 是代码织入的技术,代码织入一般有3大类:在编译期就织入,相当于拿到的class文件都已经是做好了的,一般都是用工具之类生成;在加载期织入,在类加载到jvm前使用字节码修改技术修改class内容,然后再扔给jvm来运行,java有javaagent模式来实现,通过设置一个代理,在运行之前先交给代理来处理修改。我们用idea破解应该经常能看到,甚至我们在idea上面运行的一个程序的时候,可以看到idea的控制台参数 也有个-javaagent 参数。
在这里插入图片描述
最后就是初始化一些环境变量相关的bean

postProcessBeanFactory(beanFactory);

一个给子类复写的空方法,可以在上一步prepareBeanFactory准备factory之后再来设置点factory相关的东西。

invokeBeanFactoryPostProcessors(beanFactory);

实例化且执行工厂的后置处理器。
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
执行过程中 优先去查找BeanDefinitionRegistryPostProcessor 这类和bean定义信息相关联的后置处理器,调用他的postProcessBeanDefinitionRegistry方法设置beanDefinition的注册器,然后再以此按照 实现了有优先级的接口、有排序接口、其他的,这种顺序进行调用他们的后置处理器

registerBeanPostProcessors(beanFactory)

实例化且注册beanPostProcessors到factory中
可以发现注册的地方很多地方都是用beanFactory.getBeanNamesForType()这个方法来获取factory的后置处理的全路径名,然后再通过getBean的方法来生成bean。
这里也同样做了个排序,优先级,一般排序,其他,依次注册,并且最后又做了一次对ApplicationListenerDetector的监听者的后置处理器注册,这个在prepareBeanFactoty里面注册过一次,这里又一次注册,会把他放到队尾,说是for picking up proxies 为了获取代理? 这个地方不大懂。

initMessageSource()

初始化国际化i18资源

initApplicationEventMulticaster()

初始化事件广播器,默认new 一个SimpleApplicationEventMulticaster实例对象注册到bean容器里。

onRefresh()

又是一个给子类重写的空方法。

registerListeners()

注册监听者,这里的注册只是把监听者放入ApplicationEventMulticaster中让他来管理 事件的通知。
这里有一步针对FactoryBean 这种类型的处理,这个地方没有马上把他实例化出来,考虑到factoryBean如果自己本身也是个bean,那么就可能会有后置处理器处理到他们。

finishBeanFactoryInitialization(beanFactory)

实例化所有非懒加载的单例

	// Initialize conversion service for this context.
		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.
		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
		}

设置一个值内嵌的处理器,这里用于在注解上 ${xxx${}}这种的解析

// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}

创建装载期代码织入的aware的bean

	// Stop using the temporary ClassLoader for type matching.
		beanFactory.setTempClassLoader(null);

不再使用之前的在prepareBeanFactory里面的设置的application内部的类加载器,设置为空,这里留个疑点?我也不明白为什么这么做,是为了跟其他的组件比如springboot springweb等做一个适配切入点么?

	// Allow for caching all bean definition metadata, not expecting further changes.
		beanFactory.freezeConfiguration();

冻结现在的所有的bean的定义元数据 里面操作就是设置了个标志位

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

这个是核心,这里完成创建剩余的赖加载的bean,因为之前我们也创建过bean 只不过那些bean是spring内部的bean ,比如后置处理器。

	// 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.
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				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<Boolean>)
											((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				else {
					getBean(beanName);
				}
			}
		}

拿到bean的定义信息,遍历进行bean的创建。
MergedLocalBeanDefinition指得是那些有父子继承关系的bean ,比如xml上面写的parent=xxx ,那么如果是有parent的bean ,可以把已经实例化了的parent的一些属性给复制到子bean里面去。

FactoryBean 是一种实现了FactoryBean 接口的bean ,这个接口有个getObject的方法,通过这个方法我们自己定义生成bean。然后这个实现了FactoryBean的类 可以本身也是个Bean ,因为需要区别对待,这种bean的beanName都会前缀 & 来标志他是个factorybean. 我们获取的时候需要拼接这个**&+beanName**。需要判断他是不是懒加载的,如果不是那就getBean来创建。

核心方法 getBean
	final String beanName = transformedBeanName(name);

beanname的名字转换成全限定名

Object sharedInstance = getSingleton(beanName);

查找bean实例是不是已经存在,这里查找有讲究

Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;

涉及到三个集合容器


	/** Cache of singleton objects: bean name --> bean instance */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** Cache of singleton factories: bean name --> ObjectFactory */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** Cache of early singleton objects: bean name --> bean instance */
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

singletonObjects 为最终完整的bean实例容器 俗称一级缓存
earlySingletonObjects 为早期的bean实例容器,里面的依赖等属性 还没有设置完全。为什么会有着这种状态,因为可能存在循环依赖,比如A属性里面有个B ,B的属性里面又有A,相互循环了,那么当我实例化A的时候 发现B,我得去实例化B,实例化B的时候又需要实例化A ,但是此时A又没有实例化完全,因为我们需要把A这种没有实例化完整的对象给暂存起来,这就是早期对象。俗称二级缓存
singletonFactories 这个不是存bean对象的容器,这个是存一个beanName 与 一个接口的表。这个接口叫ObjectFactory,唯一的函数是getObject(),和BeanFactory接口很像, 这个接口是为了后面给这个beanName对应的对象做一次加工。俗称三级缓存

回到那个getSingleton接口,可以发现他是首先查找完整容器bean实例,如果没有继续查找早期bean容器,再没有的话再找bean的回调函数表,如果有这个记录,那么就调用这个回调函数getObject 得到一个Object对象,然后再把他放入早期bean容器,并且把现有表的记录删除,这里我们知道了早期对象的产生是来源于调用ObjectFactory表的函数。

回到doGetBean方法,

	if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

假如找到了,那么这个对象有2种,一种是完整的bean,一种是早期bean。
isSingletonCurrentlyInCreation 判断是否已经正在创建中,看log信息可推测这种情况是因为出现了循环依赖而返回的早期对象,先实例化A 那么会记录下当前A在创建中,A依赖B,继续去创建B,B也被记录,然后B又依赖A ,找A 发现A曾被记录到,还在创建中,因此这个A是早期对象;

查阅getObjectForBeanInstance,这个方法主要针对FactoryBean这一类处理,目前bean有2种,一种是已经完整bean,一种是早期bean,不过还要再细分2种,一种是FactoryBean ,一种是非FactoryBean。

		// Don't let calling code try to dereference the factory if the bean isn't a factory.
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
			}
		}

		// Now we have the bean instance, which may be a normal bean or a FactoryBean.
		// If it's a FactoryBean, we use it to create a bean instance, unless the
		// caller actually wants a reference to the factory.
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}

看这个判断如果是beanName前面有&符号的直接返回,如果他不是factoryBean类型也直接返回。
但是如果是这2种之外的情况:属于factoryBean 且他前面没有&符号,那么他还要单独处理。

	Object object = null;
		if (mbd == null) {
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// Return bean instance from factory.
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton.
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}

下面就是对当你getBean(xxx) ,xxx是一个factoryBean类型时候,且beanName前面也没有&符号,那么需要调用他的FactoryBean的getObject方法,继续追踪getObjectFromFactoryBean 可以发现自定义获取bean的对象是存在单独的容器中factoryBeanObjectCache,而不是之前的一级缓存。
因此可以总结到,如果我们想要获取FactoryBean本身那么需要拼接 & 来获取,如果你不加&符号,那么他返回的是getObject方法返回的bean。

下面分析另一种情况,如果我们一开始就没有从getSingleton方法拿到东西。

	// Create bean instance.
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

主要看getSingleton(String beanName, ObjectFactory<?> singletonFactory)
这个方法2个参数,bean名字和一个ObjectFactory,前面说了这个就是三级缓存。

首先从一级缓存查询,有就直接返回。
一级缓存没有,beforeSingletonCreation(beanName); 设置标志位当前正在创建这个bean
调用传来的ObjectFactry的接口getObject 得到完整的bean
调用afterSingletonCreation(beanName); 移除正在创建标志
addSingleton把bean 放入一级缓存,二三缓存移除。创建结束。

创建bean

下面核心落到ObjectFactry.getObject上面这个参数是从外面以lambda表示式方式传入,看这个createBean方法是如何返回一个完整的bean

获取bean定义信息 获取其class
设置方法重载等一些标志信息

// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}

resolveBeforeInstantiation方法 :
顺序执行InstantiationAwareBeanPostProcessor 的

 Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)

注意这里会得到一个Object对象,且传入的不需要bean 只需要class就行
然后将拿到的Object对象 顺序执行所有的BeanPostProcessor的

Object postProcessAfterInitialization(Object bean, String beanName)

这里的postProcessAfterInitialization是需要bean参数的。
如果最终返回的bean !=null 返回就直接返回。 那就是说如果InstantiationAwareBeanPostProcess的beforeInstantiation返回就是null或者没有这类的postPorcess的话那么这里就不会直接返回。

继续往下看如果返回的null 就是另一个分支走向
执行

Object beanInstance = doCreateBean(beanName, mbdToUse, args);

首先需要拿到BeanWrapper,BeanWrapper 是一个实例对象的bean的一个包装 提供了一些额外的功能,比如拿到PropertyDescriptor 一些反射的方法。创造BeanWrapper中会调用instantiateBean 进行一个实例化ctor.newInstance(args) ,此时只是实例化,跟我们new T()效果一样,目前还没有对属性进行填充。

applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

这里会顺序执行 MergedBeanDefinitionPostProcessor 的
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
这里主要是提供一个再次对Bean定义信息的一个处理入口。


		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

如果是单例且允许循环依赖,那么就把beanName 和 相应的ObjectFactory接口放入三级缓存。

	populateBean(beanName, mbd, instanceWrapper);

对属性进行填充

			exposedObject = initializeBean(beanName, exposedObject, mbd);

执行BeanNameAware BeanClassLoaderAware BeanFactoryAware接口 。
执行BeanPostProcess的postProcessBeforeInitialization方法 会调用ApplicationContextAwareProcessor 后置处理器invokeAwareInterfaces方法,执行EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware,ApplicationEventPublisherAware,MessageSourceAware,ApplicationContextAware的set回调方法。
执行InitializingBean.afterPropertiesSet();方法。
执行配置的init-method的方法。
执行BeanPostProcess的 postProcessAfterInitialization方法。

之前放入三级缓存的接口中持有了当前这个实例的一个引用,目前这个bean只有三级缓存中有,之前讲过getSingleton方法他会一次去查找缓存,如果落到三级缓存中,他会去调用这个ObjectFactory的接口,生成的对象存入二级缓存。
因此如果允许循环引用的时候,我们得调用一次,拿到早期对象。

在这里插入图片描述
但是仔细观察这个allowEarlyReference 参数 是false ,他不会去查找三级缓存,只会查询一二级缓存。
1.假设有循环依赖,还是拿A B举例子, 当依赖的B在populate 属性的时候,发现需要用到A,调用getBean(A) -> 调用getSingleton(A),此时调用三级缓存的A的FactoryBean接口,拿到早期bean移到二级缓存。那么当这个时候调用allowEarlyReference=false的重载方法就能找到早期对象。
2.如果没有循环依赖那么返回的就是null ,最终的bean还是原来的exposedObject。

那么拿到的早期对象和当前对象什么时候出现不一致的情况?
出现不一致的情况只有一个,就是exposedObject = initializeBean(beanName, exposedObject, mbd);被修改了, 当对象在被被调用到BeanPostProcess的
postProcessBeforeInitialization和postProcessAfterInitialization 2个方法的时候会被修改到,导致原来的bean和exposedObject 不一致。
在这里插入图片描述

因此我们可以得知AOP处理的位置,可以查看AbstractAdvisingBeanPostProcessor类

再后面这段
在这里插入图片描述

如果存在上诉所有的循环依赖中 依赖的还是个代理对象,那么这里会收集依赖的bean 抛出异常打印日志。
参数allowRawInjectionDespiteWrapping标志 默认是false ,就是表示不允许存在这种情况。

最后记录需要销毁操作的bean ,有3种 DestructionAwareBeanPostProcessor的后置处理器,实现了DisposableBean接口的bean,以及自定义配置的destroy-method,以供当bean销毁的时候进行回调。
在这里插入图片描述
到此Bean的实例化结束

finishRefresh

发送Spring 容器初始化完成后的一系列的事件。
clearResourceCaches(); 清空不会再用到的Resource文件缓存
initLifecycleProcessor(); 创建一个DefaultLifecycleProcessor的后置处理器
getLifecycleProcessor().onRefresh(); 调用DefaultLifecycleProcessor的onRefresh方法 :获取多个Lifecycle的bean进行分组排序 然后调用他们的start方法。
publishEvent(new ContextRefreshedEvent(this)); 发送ContextRefreshedEvent容器刷新事件
LiveBeansView.registerApplicationContext(this); jmx相关的注册

关于AOP和循环依赖的思考

看源码AOP的入口有2个,一个是提前引用被其他依赖调用到三级缓存的ObjectFactory工厂,然后放入了二级缓存;另一个是最后一部初始之后调用BeanPostProcessor的afterInitialization的增强方法。
下面做个假设分析:

  1. 如果只考虑循环依赖,不考虑动态代理的问题,其实只需要1个缓存就足够,有的博客说需要2个。但是如果没有代理,只存在简单的循环依赖,根本不需要提前创建,每次在创建后还没有填充完属性前,直接先放入一个缓存,然后当另一个bean依赖时候直接引用到缓存的这个对象,原来的bean继续属性填充,引用仍然没变,没有问题。
  2. 如果只考虑代理,不考虑循环依赖,那么当属性填充完,初始化init完,最后一步调用afterInitialization再创建代理对象非常合适。
  3. 如果考虑到代理+循环依赖,那么当被其他bean引用到时候,那么就需要提前拿到最后的代理对象,再整理下顺序,A创建开辟空间>A马上放入一个缓存X 解决循环依赖> A填充属性>填充A里面的属性B>B创建开辟空间>B也放入一个缓存X>B填充属性>填充B里面的A>缓存有A。 这里A 假设需要被代理,那么B需要的肯定是被代理后的A ,那么**缓存有A>生成A的代理对象A+,A+也必须放缓存,且只有一份 ** ,再引用给B。 问题来了,当B完成之后,回到A的填充位置,当A填充属性完,目前进行的是A ,然而B引用的以及最终需要的是A+, 那么填充好的原始A是需要和代理A+对象做一次转行,这里我想得太复杂了,其实Spring生成的代理对象里面就已经持有了原始A,增强的时候只需要在配置好的切点进行增强处理就行。

把这些可能会发生的情况都兼容到,需要3个缓存,首先一个是肯定是放最终成熟的bean,另一个就是需要存获取代理对象所需要的材料,就是原始bean 以及他的一些属性比如beanDefinition等,这个在源码中是做成了BeanFactory接口的三级缓存,只有当被循环依赖到需要提前用到的时候才会调用,且如果禁止循环依赖这一步都不会做,就只会用到一级缓存。而对于二级缓存,这一点 我感觉还是因为Spring的为了让代码更清晰,单一指责。其实做成2个也是可以的,不过代码会复杂起来了,因为成熟的bean和不成熟的代理bean 混在一起了,查找起来需要增加一些标志,比较麻烦。

还有一个细节点,在创造bean的过程中返回的bean最终是要放入一级缓存的,如果是代理对象,它最终返回的也应当是在二级缓存的引用,他是在最后一部的afterInitialization中被返回的,调用到了spring的aop处理器AbstractAutoProxyCreator
在这里插入图片描述

这个方法和获取提前代理对象的方法getEarlyBeanReference很像
在这里插入图片描述
如果之前被提前生成的代理对象,那么这里的缓存Set earlyProxyReferences 就会有,直接返回到之前创建的代理,最后存入一级缓存,移除二三级缓存。

小结

至此,Spring的核心流程都讲完了。还有一些非常细节的处理还需要再深入深入。总体来讲Spring的大多数套路都是围绕各种PostProcessor来来进行的,给生命周期的各个点进行回调处理,都是这种执行前,执行后要做什么样的修改等。这种设计结构在很多框架都能看到,这种魔板设计模式也是很多应用程序代码做拓展增强时一种手段,一般对于核心框架都是要确保足够灵活拓展性要强,避免过重依赖,把一些自定义个性化的都交个客户自己来实现。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值