本章目标
1.getBean方法的解析
2.@propertySource和@ConfigurationProperties生效的问题.
3.后期还会解析其内嵌式tomcat如何运作
4.解析整个整个spring容器的运转流程
5.总结整个springboot启动流程的总结
6.用processon画上面的流程图
getBean调用的是AbstractBeanFactory的doGetBean方法,实际生产bean的方法是AbstractAutowireCapableBeanFactory类的createBean
具体源码如下:
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
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);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 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);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final 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, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
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;
}
}
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
- 1.
transformedBeanName是去掉原始的beanName的&然后拿到修改后的beanName去循环获取别名从而找到最终beanName - 然后调用getSingleton(beanName)去获取beanInstance,此时allowEarlyReference=true
- 3.如果beanInstance获取成功就调用
getObjectForBeanInstance,该方法是判断是否返回bean本身还是factorybean,具体逻辑如下
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
如果name包含&然后看beanInstacne是否可以返回,如果返回的实例不等factoryBean,就抛出异常
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}
到这一步就是要么name不包含&但是生产的bean不是factroybean,要么就是包含&生成的是factorybean本身
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
if (mbd == null) {
尝试从factoryBeanObjectCache获取真正的对象
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// 获取失败到这边我们已经可以确定beanInstance就是factorybean
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
获取merged的bean
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
- 3.如果beanInstance为null,且isPrototypeCurrentlyInCreation为true代表遇到了原型(非单例)循环依赖,所以抛出异常
循环依赖的总结:
- 1、首先无论是单例还是原型都不支持构造函数注入的循环依赖,具体原因就是因为是依靠构造函数的,所有bean永远无法实例化成功,从而无法获取bean(原型需要主动调用bean才会触发异常)
- 2.对于原型bean的其他循环依赖注入也无法支持,因为原型的bean, spring 是不缓存,所以永远都无法获取到在构造函数中依赖的bean
- 3.对于单例非构造函数的依赖注入,通过提前将实例化但是未初始化bean缓存起来,等到依赖的双方都实例化,互相赋值然后互相填补bean的属性。
- 4.isPrototypeCurrentlyInCreation的逻辑就是:prototypesCurrentlyInCreation是一个threadlocal,因为是prototype,所以检测每一次请求生成的bean是否存在循环依赖,prototypesCurrentlyInCreation第一次存放的是第一次请求的name字符串,第二次是存放set集合,一会每次请求bean看看set集合是否存在,如果存在代表这个bean已经创建了 但是还是需要重新创建 说明此时存在循环依赖(包含构造函数和setter)
之所以用threadlocal就是一次请求一个bean理应只生成一次,如果生成多次则存在循环调用 - 5.检测是否存在父类工厂,如果存在且beanName也不在子类工厂,则调用父类的beanFactory的getBean方法
-
markBeanAsCreated(beanName);如果创建bean不是为了类型检查,则要标记当前bean已经被创建或者即将被创建以便于BeanFactory可以优化重复创建的bean的缓存 .
-
- 7.第六步也就是将beanName放入alreadyCreated,并从mergedBeanDefinitions删除该beanName对应的rootBeanDefinition
- 继续获取合并后的MergedLocalBeanDefinition,若该MergedLocalBeanDefinition是抽象类则抛出异常
- 9.获取某个beanDefinition的dependsOn,这个可以放在xml的bean标签或者@DependsOn 但是如果使用注解 那么该bean必须也是用注解生成 用xml 没有反应,<bean>标签的其他属性都是以单独的注解呈现出来的 不是和@Bean注解在一起比如 @Scope 等
-
isDependent的逻辑首先检测hashset是否已经存在,如果存在就说明不是循环依赖(这边是循环依赖,之前讲的是循环依赖注入),然后从dependentBeanMap获取当前beanName的依赖哪些beanName,然后看当前beanName和缓存中的beanName是否相同,相同就是循环依赖,让没有但是该beanName还是有其他的依赖beanName,然后检测剩余依赖的beanName是否依赖dependentBeanName,如果有就抛出异常
-
- 11.
registerDependentBean的就是创建dependentBeanMap和dependenciesForBeanMap两个缓存,他们的value是set,然后将当前的beanName和dependentBeanName分别以key和value 以及value和key的注入这两个缓存中 - 12 然后在获取dependentBeanName的bean即调用getBean(dependentBeanName)。
- 13.根据MergedLocalBeanDefinition的scope来进行生产bean,scope分为SCOPE_PROTOTYPE,SCOPE_SINGLETON,SCOPE_REQUEST,SCOPE_SESSION,ScopedProxyMode(Default,No,INTERFACES,TARGET_CLASS)
- spring生产bean 分为 sigleton,prototype和其他
- 15.单例的时候调用
getSingleton(String beanName, ObjectFactory<?> singletonFactory)这个时候也包含proxy,singletonFactory最终调用的是AbstractAutowireCapableBeanFactory的createBean,getSingleton的方法逻辑是:
1.锁定singletonObjects,然后检测缓存中是否包含beanName对应的bean,如果存在直接返回。
2.如果不存在,检测singletonsCurrentlyInDestruction是否为true,true代表该bean正在销毁。
3.inCreationCheckExclusions代表是否需要检测bean正在创建,singletonsCurrentlyInCreation代表单例正在创建的bean,即如果当前的beanName是需要创建检测的,且未正在创建才可以下一步 否则抛出异常
4.然后调用ObjectFactory的getObject方法获取bean
5.在允许创建检测的时候从singletonsCurrentlyInCreation删除当前的beanName然后若bean创建成功则放入singletonObjects和registeredSingletons(放入beanName),删除singletonFactories和earlySingletonObjects
重点createBean
1.不论scope是什么,创建bean都是采用AbstractAutowireCapableBeanFactory的这个方法
2.调用resolveBeanClass得到beanCalss,假如beanDefinition的beanCalss和beanName都不存在且解析后的beanClass存在 ,那么就是用该beanClass进行实例化。
3.resolveBeanClass的逻辑:1.如果原先就有beanClass就立即返回。2.调用doResolveBeanClass方法。
4.doResolveBeanClass的方法逻辑:1.如果typesToMatch存在就把他们的className都放入tempClassLoader的excludedClasses中,即typesToMatch不会去生成class对象。2.获取className,当className为null 直接调用RootBeanDefinition的resolveBeanClass否则 先获取根据scopeName从scopes获取Scope并采用beanExpressionResolver
5.其中beanExpressionResolver是在prepareBeanFactory通过beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));其作用至今没看明白
6.获取到最终的className 然后调用class.forName方法生成class
7.mbdToUse.prepareMethodOverrides();,是检测当前的lookup-method和replace-method,都是通过cglib代理
8.replace-method必须实现MethodReplacer接口的Bean才能替换,而lookup-method则由BeanFactory自动为我们处理了。
public class RootBeanClass implements MethodReplacer {
public void say() {
System.out.println("RootBeanClass");
}
@Override
public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
System.out.println(method.getName());
return null;
}
}
<bean id="childBeanClass" class="com.marshall.testRooAndChildBeanDefinition.ChildBeanClass">
<replaced-method name="say" replacer="rootBeanClass"></replaced-method>
</bean>
<bean id="rootBeanClass" class="com.marshall.testRooAndChildBeanDefinition.RootBeanClass"
>
</bean>
9.这边有个优化就是当我们的look-upmethod or replace-method 没有歧义 即只在父类和父类的中只找到了一个方法名字(这个方法包含方法名字一样但是 参数不一样的) 那么下次就不需要在迭代去寻找了
10.resolveBeforeInstantiation的意思在实例化前解析,通过determineTargetType获取class 获取不到就不往下面执行,determineTargetType(首先尝试从factoryMethod获取class 或者从factory-bean获取beanclass,否则根据className获取class)
在获取到了class之后即给实现了InstantiationAwareBeanPostProcessor接口的bean一次修改bean的机会,InstantiationAwareBeanPostProcessor接口继承了BeanPostProcessor,BeanPostProcessor是在初始化前后进行操作,InstantiationAwareBeanPostProcessor还增加了一个postProcessPropertyValues,大部分默认的实现都是直接返回PropertyValues,只有AutowiredAnnotationBeanPostProcessor 去实现了他 对@Autowire 和@Value 进行了属性注入,如果我们撰写InstantiationAwareBeanPostProcessor 该方法 写了 return null 会导致注入失败,同样postProcessAfterInstantiation如果返回false 也会导致不会继续注入相关属性
11.resolveBeforeInstantiation是先对bean实例化前进行操作(BeanPostProcessorsBeforeInstantiation),如果实例化成功在调用对bean进行初始化(BeanPostProcessorsAfterInitialization)之所以这样是因为当bean不为空时候不会再调用doGetBean方法去生成bean,此时只有在这有机会调用实例化后的初始化。 此外spring在这里只是对自定义TargetSource生成代理
12.继续分析
resolveBeforeInstantiation如果其得到了bean则直接返回,否则就是调用doCreateBean方法 这个方法就是spring最终生成bean,并且填充bean并完成动态代理的地方
@propertySource和@ConfigurationProperties生效的问题.
1.当执行到AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsBeforeInitialization方法
2.通过调用ConfigurationPropertiesBindingPostProcessor的postProcessBeforeInitialization方法获取@ConfigurationProperties的bean 并对其进行赋值操作