前言
上面一章,说明了bena
的解析与注册,这些都是未bean加载做的准备工作,真正复杂的还是bean
的加载,但是通过前面的学习,我们也会清楚了各个类在spring
容器的职责,这样就可能理解他们的使用,当我们进行扩展时就会更清晰明了,不会看到别人的代码一头雾水,比如下面这段代码的理解
/**
* 注册bean
*/
public class RegisterBeanFactory implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// 注册bean 这里就是省略了解析,因为解析实际上就是构建BeanDefinition
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(ProxyBeanFactory.class);
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(beanDefinition, "userDao");
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
}
}
上面的代码就是手动注册一个bean
到容器中,如果看了之前的文章是不是就很明了了呢,现在我们来看看bean
的加载
bean加载
从这段代码开始
BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config.xml");
UserDao userDao = beanFactory.getBean("userDao", UserDao.class);
getbean方法就是加载的开始,真正的实现就是在AbstractBeanFactory类的doGetBean方法
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
// 提取对应的beanName
String beanName = this.transformedBeanName(name);
// 检查缓存中或者实例工厂中是否有对应的实例
// 原因是创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖
// Spring的解决方案是不等bean创建完成就会创建bean的ObjectFactory提早曝光
// 就是将ObjectFactory加入缓存,一旦下一个bean创建时需要依赖上一个bean则直接使用缓存中bean'Factory
// 直接尝试从缓存获取,或者singletonFactories的ObjectFactory获取
Object sharedInstance = this.getSingleton(beanName);
Object beanInstance;
if (sharedInstance != null && args == null) {
if (this.logger.isTraceEnabled()) {
if (this.isSingletonCurrentlyInCreation(beanName)) {
this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
} else {
this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} else {
// 只有单例模式下才会尝试解决循环依赖,原型模式下如果存在依赖,那么就会抛出异常
if (this.isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
BeanFactory parentBeanFactory = this.getParentBeanFactory();
// 如果beanDefitionMap找不到beanName则会尝试从parentBeanFactory中找
if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
String nameToLookup = this.originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
}
if (args != null) {
return parentBeanFactory.getBean(nameToLookup, args);
}
if (requiredType != null) {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
return parentBeanFactory.getBean(nameToLookup);
}
if (!typeCheckOnly) {
this.markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
// 将GenericBeanDefinition转换为RootBeanDefinition,如果指定的bean是子bean那么会合并父bean信息
RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
this.checkMergedBeanDefinition(mbd, beanName, args);
String[] dependsOn = mbd.getDependsOn();
String[] var12;
// 如存在依赖,就要递归实现依赖的bean
if (dependsOn != null) {
var12 = dependsOn;
int var13 = dependsOn.length;
for(int var14 = 0; var14 < var13; ++var14) {
String dep = var12[var14];
if (this.isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 缓存以来调用
this.registerDependentBean(dep, beanName);
try {
this.getBean(dep);
} catch (NoSuchBeanDefinitionException var31) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var31);
}
}
}
// 实例化依赖的bean后,就开始实例化mbd本身,这个有意思,之前的理解都是本身先实例化
// 单例模式的创建
if (mbd.isSingleton()) {
sharedInstance = this.getSingleton(beanName, () -> {
try {
return this.createBean(beanName, mbd, args);
} catch (BeansException var5) {
this.destroySingleton(beanName);
throw var5;
}
});
beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
// 原型模式创建
var12 = null;
Object prototypeInstance;
try {
this.beforePrototypeCreation(beanName);
prototypeInstance = this.createBean(beanName, mbd, args);
} finally {
this.afterPrototypeCreation(beanName);
}
beanInstance = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ��" + beanName + "'");
}
Scope scope = (Scope)this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
this.beforePrototypeCreation(beanName);
Object var4;
try {
var4 = this.createBean(beanName, mbd, args);
} finally {
this.afterPrototypeCreation(beanName);
}
return var4;
});
beanInstance = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException var30) {
throw new ScopeNotActiveException(beanName, scopeName, var30);
}
}
} catch (BeansException var32) {
beanCreation.tag("exception", var32.getClass().toString());
beanCreation.tag("message", String.valueOf(var32.getMessage()));
this.cleanupAfterBeanCreationFailure(beanName);
throw var32;
} finally {
beanCreation.end();
}
}
return this.adaptBeanInstance(name, beanInstance, requiredType);
}
以上代码就是spring加载bean的过程,下面我们来一步步分析一下
转换对应的beanName
这部分对应的就是
transformedBeanName
方法/** *返回实际的 bean 名称,去掉工厂引用 * 前缀(如果有,也去掉重复的工厂前缀,如果找到)。 * @param name bean 的名称 * @return 转换后的名称 * @see *BeanFactory#FACTORY_BEAN_PREFIX */ public static String transformedBeanName(String name) { Assert.notNull(name, "'name' must not be null"); if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) { return name; } return transformedBeanNameCache.computeIfAbsent(name, beanName -> { do { beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length()); } while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)); return beanName; }); }
既然我们之间解析和注册的时候已经明确了
beanName
那么为什么还要转换呢,从这个方法的注释我们可以知道,beanName
有可能有前缀如&,那么这样就要把他去掉,另外我们定义bean
的时候可能会用到alias
别名,这里的别名就要进行转换,比如别名A指向beanB
,那么别名A要返回beanB
- 尝试从缓存中加载依赖
这部分主要是为了解决循环依赖,单例的情况下,解决依赖的方式就是,在
spring bean
还没加载完,就将他里面的对象先放到缓存中ObjectFactory
,读取的时候如果缓存里面有就从缓存里面读取,如果没有就从singletonFactories
中读取。 - bean的实例化
这一步时我们可能有一个疑问,
bean
不是已经在解析和注册时已经实例化到缓存BeanDefinitionResitry
中了吗?为什么还要再实例化,那是因为解析和注册后我们得到的是初始状态的bean
,而我们真正需要的bean
是facoty-mthod返回的bean,他的创建是由getObjectForBeanInstance
方法来完成的 - 原型模式下判断循环依赖
spring
会对循环依赖处理都是在单例模式下,如果原型模式出现了这种情况会直接抛出异常 - 检测parentBeanFactory
如果当前的缓存中没有找到beanName的配置,那么就去
parentBeanFactory
中查找,找到后再通过递归调用getBean
方法。 - 存储xml文件的GernericBeanDefinition转换为RootBeanDefinition
spring的后续处理都是针对
RootBeanDefinition
进行处理的,所以我们要把解析后的GernericBeanDefinition
转换成RootBeanDefinition
寻找依赖
spring bean
的创建过程中,要先创建bean中的属性,比如depends-on="jedisPoolConfig"
<!-- jedis pool配置 --> <bean id="jedisPool" class="redis.clients.jedis.JedisPool" destroy-method="destroy" depends-on="jedisPoolConfig"> <constructor-arg ref="jedisPoolConfig" /> <constructor-arg value="127.0.0.1" /> <constructor-arg type="int" value="6379" /> </bean>
depends-on="jedisPoolConfig"
在实例话前加载
- 针对不同的scope进行加载
singleton,prototype,request多种scope
获取单例bean
从前面的代码中了解到,单例在spring容器只会创建一次,后续都是从缓存或者singletonFactoty中获取,为了解决循环依赖,spring会在不等bean创建完成就将创建bena的beanFactory提早曝光,下面看看他的实现
getSingleton方法
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
// 锁定全局变量并进行处理
synchronized (this.singletonObjects) {
// 缓存中是否存在实例
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 调用预先设定的getObjct方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 记录到缓存中
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
从bean实例中获取对象
在这一步前面的过程分别是 解析-注册-从不同的scope中获取bean,那么这一步就是终极加载,前面的流程中获得的bean其实都是初始状态的bean,而这一步就是要在前面的基础上加料了,这一步对应的方法就是getObjectForBeanInstance方法
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 如果指定的name是工厂相关&前缀,且beanInstace又不是Factory则验证不通过
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
// 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)) {
return beanInstance;
}
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
// 尝试从缓存中加载
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory. 明确知道beanInstance是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);
}
return object;
}
主要工作就是
- 对FactoryBean进行验证
- 对非FactoryBean不做处理
- 对bean进行转换
- 最后委托给getObjectFromFactoryBean方法
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
beforeSingletonCreation(beanName);
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
// 这里面直接调动了FactotyBean的getObject方法
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
// 调用ObjectFactory的后置处理器
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
从代码中可以看出,其实在加载完bean后又执行了一个调用后置处理器的操作,这个操作就是为了以后对spring加载bean的灵活拓展
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}