springboot源码分析(七)-getBean()
概述
这个⽅法我们并不陌⽣,通常我们在程序中都会先获取到ApplicationContext,之后调⽤getBean()⽅法获取bean,那这个⽅法是如何获
取的bean呢?下⾯就来分析⼀下
getBean()⽅法
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
doGetBean()⽅法
这⾥我先说⼀下这个⽅法的调⽤流程
1. 转换beanName的名称,因为Bean和FactoryBean不同,获取bean的⽅法不同,如果要想获取FactoryBean,需要在beanName前⾯
加上&符号
2. 从singletonObjects中获取,实例化好的bean都会放到这个容器中
3. 如果singletonObjects不存在,就从bean的⽗bean中寻
4. 如果⽗bean中也不存,就要执⾏创建过程了,第⼀步合并beanDefiniton(因为bean可能继承了很多的⽗类,把所有的属性合并,以字
类的属性优先)
5. 判断bean有没有依赖的bean,如果有,先创建依赖的bean
6. 判断bean是单例模式还是原型模式,还是以上两者都不是,不同的模式采⽤不同的创建⽅法
7. 创建完成
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//1. 如果name不是以&开头,直接返回name,如果是以&开头,去掉&,有多少去掉多少,之后返回,并且把name,和去掉&之后的name作为key-value存⼊⼀个 //缓存map中
//2. 转换别名,获得bean的真名
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.//如果拿到单例bean直接返回
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
}
}
// 为什么要调⽤ getObjectForBeanInstance ⽅法,判断当前Bean是不是FactoryBean,如果是,那么要调⽤getObject⽅法
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
//如果bean没有创建,从⽗容器查beanName对应的bean,如果存在就直接返回
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
实例化bean的三种方式//这⾥使⽤了⼀个threadlocal包裹这个⼀个对象,⽤来处理循环依赖,后⾯看⼀下这个是怎么解决循环依赖的
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
//这⾥的parentBeanFactory是在初始化的时候赋值的,但是这个初始化的过程中调⽤的是⽆参构造函数,并没有
//赋值,还有⼀个地⽅就是setParentBeanFactory,这个也可以赋值,但是没有到是在哪⾥调⽤的
BeanFactory parentBeanFactory = getParentBeanFactory();
//判断当前类的⽗类是否为空和在之前从xml中加载bean的时候有没有把这个name放⼊到ioc的那个map中
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
//parentBeanFactory就是⽗容器,从⽗容器中获取
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) Bean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
Bean(nameToLookup, requiredType);
}
else {
return (T) Bean(nameToLookup);
}
}
if (!typeCheckOnly) {
/
/将当前的name放⼊alreadyCreated这个map中
markBeanAsCreated(beanName);
}
try {
//这⼀步返回的实际上是MergeBeadDefinition,什么意思呢,就是⼀个bean可以设置parent属性,
//但是这个parent并不是常说的继承来的parent,⽽是在定义bean的时候可以设置,那下⾯的⽅法其实就是
//把⽗类中的⼀些属性赋值给字类,如果字类中也存在该属性的值,优先使⽤字类的,如果字类不存在就是使⽤⽗类的 //这⾥科普个关于BeanDefinition的例⼦,这个就是AbstractBeanDefinition,这个是所有具体实现的beanDefinition
//的抽象⽗类,然后有⼏个具体实现的字类RootBeanDefinition,GenericBeanDefinition,ChildBeanDefinition,有这三个 //实现类,其中第⼀个不能拥有parent
//如果⽗容器中不存在,就合并beanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//判断mbd是不是抽象的
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
//这个可能来⾃于上⾯根据beanName得到的那个mbd
//检查是否有依赖的bean,如果有,先实例化依赖的bean
String[] dependsOn = DependsOn();
//当前来看,我的例⼦这个为null
//如果有依赖的bean,解决循环依赖的问题
if (dependsOn != null) {
//通过for循环把依赖的map全部是实例化放⼊到容器中
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new ResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
//将依赖的map放⼊依赖map中
registerDependentBean(dep, beanName);
try {
//在这⾥获取依赖的bean,如果这⾥存在循环依赖就会有问题
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new ResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
if (mbd.isSingleton()) {
//有了beanDefinition,创建bean,这个getSingleton其实就是调⽤了ObjectFactory中的getObject⽅法
//这⾥最重要的是才createBean⽅法
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;
}
});
/
/这⾥是说看⼀下上⾯创建的那个shareInstance是是⼀个什么类型的bean,如果是factoryBean之类的需要调⽤ //⼀下getObject()获取真正的bean
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//创建prototype类型的bean
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);
}
//创建其他类型的bean
else {
String scopeName = Scope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
}
final Scope scope = (scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = (beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
以上⽅法调⽤的⼦⽅法很多,我分析⼀下createBean(),剩下的⼀些⼦⽅法⼤家⾃⼰看⼀下createBean()⽅法
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
}
//这⾥的mbd就是合并之后的beanDefinition,这⾥搞了⼀个副本,之后的操作都是基于副本的
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
//1.解析beanName对应的bean类型,⽐如st.IOCServiceImpl
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
// 如果resolvedClass存在,并且mdb的beanClass类型不是Class,并且mdb的beanClass不为空(则代表beanClass存的是Class的name), if (resolvedClass != null && !mbd.hasBeanClass() && BeanClassName() != null) {
// 则使⽤mdb深拷贝⼀个新的RootBeanDefinition副本,并且将解析的Class赋值给拷贝的RootBeanDefinition副本的beanClass属性,
// 该拷贝副本取代mdb⽤于后续的操作
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
// 2.验证及准备覆盖的⽅法(对override属性进⾏标记及验证)
//这⾥就是为了解决xml中配置的什么lookup-method,这⾥做的操作就是对于存在override的bean做⼀个标记
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new ResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 3.实例化前的处理,给InstantiationAwareBeanPostProcessor⼀个机会返回代理对象来替代真正的bean实例,达到“短路”效果
//这个就是aop操作的,在切⾯前编程
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
// 4.如果bean不为空,则会跳过Spring默认的实例化过程,
return bean;
}
}
catch (Throwable ex) {
throw new ResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 5.创建Bean实例(真正创建Bean的⽅法)
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
}
}
这个⾥⾯有两个⽐较重要的⽅法
resolveBeforeInstantiation(beanName, mbdToUse);
doCreateBean(beanName, mbdToUse, args);
第⼀个⽅法和aop有关,下篇⽂章在分析,下⾯分析⼀下第⼆个⽅法
这个⽅法处理流程
实例化bean,但是这个bean是没有属性的
填充属性
解决循环依赖
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
//从这个缓存中移除并获取
instanceWrapper = ve(beanName);
}
if (instanceWrapper == null) {
//创建bean,有三种⽅式
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//这⾥的bean是没有填充属性的,是⼀个空的bean
final Object bean = WrappedInstance();
Class<?> beanType = WrappedClass();
if (beanType != NullBean.class) {
}
// Allow post-processors to modify the merged bean definition.
// 这⾥⼜遇到后置处理了,此处的后置处理是⽤于处理已“合并的 BeanDefinition”
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new ResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
/**
* earlySingletonExposure 是⼀个重要的变量,这⾥要说明⼀下。该变量⽤于表⽰是否提前暴露
* 单例 bean,⽤于解决循环依赖。earlySingletonExposure 由三个条件综合⽽成,如下:
* 条件1:mbd.isSingleton() - 表⽰ bean 是否是单例类型
* 条件2:allowCircularReferences - 是否允许循环依赖
* 条件3:isSingletonCurrentlyInCreation(beanName) - 当前 bean 是否处于创建的状态中
*
* earlySingletonExposure = 条件1 && 条件2 && 条件3
* = 单例 && 是否允许循环依赖 && 是否存于创建状态中。
*/
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
"' to allow for resolving potential circular references");
}
// 添加⼯⼚对象到 singletonFactories 缓存中,在第⼀步中getSingleton,有从这个缓存singletonFactories获取 //⼯⼚,之后创建bean
addSingletonFactory(beanName,
// 获取早期 bean 的引⽤,如果 bean 中的⽅法被 AOP 切点所匹配到,此时 AOP 相关逻辑会介⼊
() -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 向 bean 实例中填充属性,populateBean ⽅法也是⼀个很重要的⽅法,后⾯会专门写⽂章分析
populateBean(beanName, mbd, instanceWrapper);
/*
* 进⾏余下的初始化⼯作,详细如下:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论