- (一)序言
- (二)Spring初始化非延迟加载单例入口
- 1、初始化非延迟加载单例bean准备:finishBeanFactoryInitialization
- 2、实例化单例bean:preInstantiateSingletons
- (三)Spring Bean加载
- 1、非延迟bean加载:doGetBean
- (四)非延迟加载bean流程
在Spring源码分析容器篇中初始化非延迟加载单例finishBeanFactoryInitialization中提到了大概,在容器篇中未进行详细分析,本文是对spring初始化非延迟加载单例详细分析,也是笔者对spring深入学习的过程,文中有出错的地方,还望大家能够及时指出。
(二)Spring初始化非延迟加载单例入口本次入口分析是Spring容器篇中第11步finishBeanFactoryInitialization->preInstantiateSingletons方法,初始化非延迟加载单例方法是包含了处理参数绑定、处理LoadTimeWeaverAware类型的Aop和加载饿汉式单例bean,主要是由preInstantiateSingletons方法来加载单例bean,加载饿汉式单例是本文重点分析的对象。
1、初始化非延迟加载单例bean准备:finishBeanFactoryInitialization初始化bean常规饿汉式单实例bean即非惰性的bean,经典的getBean方法被调用,代码执行到此处,BeanFactory已经创建完成,并且所有的实现了BeanFactoryPostProcessor接口的Bean都已经初始化并且其中的postProcessBeanFactory(factory)方法已经得到回调执行了。而且Spring已经“手动”注册了一些特殊的Bean,如environment、systemProperties、监听器等等。剩下的就是初始化所有的单例bean,大都数我们的业务中都是单例bean,就像我们写的@Controller、@Service的类(没有设置懒加载的)都是在这个地方初始化,以供我们使用,如果没有设置懒加载,那么Spring会在接下来初始化所有的singleton beans。
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
/**
* 容器中有配置bean名称为conversionService时,则使用getBean对其进行初始化
* conversionService类是将前端传过来的参数和后端的controller方法上的参数进行绑定的时候用
*/
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));
}
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
//获取LoadTimeWeaverAware类型的,主要是Aop的实现原理
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
//清空临时类加载器
beanFactory.setTempClassLoader(null);
//暂停临时的类加载器使用
beanFactory.freezeConfiguration();
//委托给DefaultListableBeanFactory去实例化非懒加载的单例bean(核心)
beanFactory.preInstantiateSingletons();
}
2、实例化单例bean:preInstantiateSingletons
DefaultListableBeanFactory类负责实现preInstantiateSingletons预加载实例化单例bean,只处理非抽象、单例且非懒加载的bean,包含工厂bean和单例bean,最后实例化完所有的单例bean后,如果每一个bean是否有实现SmartInitializingSingleton接口,如果有实现则执行回调方法afterSingletonsInstantiated,具体逻辑如下:
public void preInstantiateSingletons() throws BeansException {
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);//获取所有的BeanDefinitionNames
for (String beanName : beanNames) {//遍历beanNames
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);//获得BeanDefinition
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {//只处理非抽象、单例且非懒加载
if (isFactoryBean(beanName)) {//判断是否为工厂bean
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);//工厂bean时需要使用&作为前缀
if (bean instanceof FactoryBean) {
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());
}
//是否加载工厂bean
if (isEagerInit) {
getBean(beanName);
}
}
}else {
//处理非工厂bean即饿汉式加载单例bean,核心点重点分析
getBean(beanName);
}
}
}
//触发加载后的所有单例bean的后置afterSingletonsInstantiated方法即回调
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
(三)Spring Bean加载
1、非延迟bean加载:doGetBean
AbstractBeanFactory类来负责完成加载非延迟单例bean——getBean,实际由doGetBean来完成,其中核心点为规范化beanName、getSingleton缓存获取bean实例、自定义容器与spring的AbstractBeanFactory递归获取bean、优化缓存bean、处理depend-on依赖实例化、创建除单例的bean和检查返回的bean类型,代码具体逻辑如下:
public Object getBean(String name) throws BeansException {
//封装获得bean,实际实现由doGetBean
return doGetBean(name, null, null, false);
}
Spring特点之一,概念性且比较重要的统一使用方法封装,底层基本都是由doXXX来实现,下面具体重点分析doGetBean核心逻辑,代码如下:
protected <T> T doGetBean(String name, Class<T> requiredType,Object[] args, boolean typeCheckOnly)
throws BeansException {
//spring别名转化,工厂beanName转化为实际的beanName(1)
String beanName = transformedBeanName(name);
Object bean;
//从缓存中获取bean,一级缓存、二级缓存、三级缓存,后面开展循环依赖文章中重点分析(2)
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
/**
* 返回bean实例,sharedInstance可能是FactoryBean或普通bean实例
* 如果是是工厂bean则执行getObject返回,否则直接返回普通bean实例
*/
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}else {
//判断是否为原型bean,只处理单例
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
//spring容器中不存在当前bean,则进行一系列准备工作,开始着手创建bean实例
BeanFactory parentBeanFactory = getParentBeanFactory();//获取父类容器
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
//获取beanName,此处与transformedBeanName获取beanName不同,会返回普通bean和工厂bean的beanName
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
/**
* 父类容器中获取bean即AbstractBeanFactory中的doGetBean,此处其实是防止自定义容器实现doGetBean中未找到
* 则在AbstractBeanFactory容器中再次获取
* (3)
*/
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
} else if (args != null) {
// 有参数args时则委托给父类容器获取bean
return (T) parentBeanFactory.getBean(nameToLookup, args);
} else if (requiredType != null) {
// 无参数时且requiredType不为空也委托给父类容器获取bean
return parentBeanFactory.getBean(nameToLookup, requiredType);
} else {
//不满足上述if和else if条件时则默认使用父类容器获取bean
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
//getBean方法typeCheckOnly默认值为false,主要是优化缓存bean,不重复创建bean(4)
if (!typeCheckOnly) {
/**
* markBeanAsCreated中使用alreadyCreated变量负责检查bean是否为已创建或正在创建
* 如果是则改变BeanDefinition的stale为true,该值会控制是否创建
*/
markBeanAsCreated(beanName);
}
try {
//获取RootBeanDefinition,包含了自身容器和父类容器中获取
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);//检查该RootBeanDefinition是否为抽象标记,如果是则抛出异常
// 获取该BeanDefinition的依赖属性
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
/**
* isDependent方法检查该bean是否有循环依赖,如果存在相互先实例化的关系则抛出异常
* 此处的depends-on属性中是指当前bean实例化之前必须先实例化该属性值中bean,与我们常说的循环依赖是不一样的
* 该处仅仅是检查该bean必须在另一个bean实例化的前面,可以被注入也可以不被注入
* (5)
*/
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);//将其注册到dependenciesForBeanMap中
try {
getBean(dep);//开始实例化属性bean
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
//开始真正创建单例bean
if (mbd.isSingleton()) {
//使用lamda表达式来获取bean
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实例,sharedInstance可能是FactoryBean或普通bean实例
* 如果是是工厂bean则执行getObject返回,否则直接返回普通bean实例
*/
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
//处理bean为prototype类型的,直接创建(6)
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);//创建原型bean前将自身添加到prototypesCurrentlyInCreation中
prototypeInstance = createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);//创建原型bean后将自身从prototypesCurrentlyInCreation中移除
}
/**
* 返回bean实例,sharedInstance可能是FactoryBean或普通bean实例
* 如果是是工厂bean则执行getObject返回,否则直接返回普通bean实例
*/
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
//其他作用域的bean,request或session作用域(6)
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
//直接创建新的bean实例,沿用beforePrototypeCreation和afterPrototypeCreation来标记创建过程
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
});
//返回bean实例,可能是FactoryBean或普通bean实例
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",ex);
}
}
} catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 检查获取bean时是否匹配指定返回的Class类型(7)
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
//转化为requiredType类型,如果有自定义转换器时会很有效果
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
} catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
(四)非延迟加载bean流程
(1)规范化beanName:transformedBeanName方法负责普通bean的别名或去除工厂bean的前缀转化为beanName;
(2)getSingleton缓存获取bean实例:从缓存中获取bean,一级缓存(singletonObjects)、二级缓存(earlySingletonObjects)、三级缓存(singletonFactories);
(3)自定义容器与spring的AbstractBeanFactory递归获取bean:父类容器中获取bean即AbstractBeanFactory中的doGetBean,此处其实是防止自定义容器实现doGetBean中未找到则在AbstractBeanFactory容器中再次获取;
(4)优化缓存bean:getBean方法typeCheckOnly默认值为false,主要是优化缓存bean,不重复创建bean
(5)处理depend-on依赖实例化:isDependent方法检查该bean是否有循环依赖,如果存在相互先实例化的关系则抛出异常,此处的depend-on属性中是指当前bean实例化之前必须先实例化该属性值中bean,与我们常说的循环依赖是不一样的,该处仅仅是检查该bean必须在另一个bean实例化的前面,可以被注入也可以不被注入;
(6)创建除单例的bean:创建prototype、request或session作用域的bean;
(7)检查返回的bean类型:检查获取bean时是否匹配指定返回的Class类型。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)