2023-09-16
原文作者:王伟王胖胖 原文地址: https://blog.csdn.net/wangwei19871103/article/details/105041908

getBean(String name)

昨天我们讲了单例实例化的时候会先判断是否是FactoryBean类型的,是的话会进行相应处理,但是没讲最关键的getBean,现在我们就开始讲这个,可能需要很多个篇幅,里面涉及了很多东西。废话不多说,我们开始吧。这些是我们要进行实例化的单例:

202309162312064991.png
但是前面有一些已经被创建出来了,可以直接获取:

202309162312072902.png
其实我们就只要关心我们自定义的两个对象:

202309162312079803.png
我们开始吧:

202309162312085854.png

202309162312090125.png

doGetBean开始获取bean

我们来看下这个方法的参数:

    name 就是bean名字
    requiredType 表示需要的类型,如果有类型,创建后会进行类型转换
    args 表示参数,也就是构造方法的参数
    typeCheckOnly 表示只是做检查,并不是真的要用,这个会影响一些逻辑

因为代码比较长,我们分段来分析比较好,就保留和核心的代码:

doGetBean分段1

首先判断单例存在,且没有参数,这个时候还不能直接返回,还要做一些处理,因为传进来的名字可能是FactoryBean本身,也就是name=&beanName

    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;
    		//检查是否手动注册了单例
    		Object sharedInstance = getSingleton(beanName);
    		if (sharedInstance != null && args == null) {//存在单例了
    			...
    			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    		}

AbstractAutowireCapableBeanFactory的getObjectForBeanInstance

这个方法有两个重要的参数namebeanNamename是指传进来的名字,可能是FactoryBean本身的名字,有&前缀,也可能是一般的bean名字,beanName是规范后的名字,去掉了&前缀,所以要进行处理。比如这种:

202309162312094736.png

    	@Override
    	protected Object getObjectForBeanInstance(
    			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
    		//如果有正在创建的bean要建立以来关系,后面讲
    		String currentlyCreatedBean = this.currentlyCreatedBean.get();
    		if (currentlyCreatedBean != null) {
    			registerDependentBean(beanName, currentlyCreatedBean);
    		}
    
    		return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd);
    	}

AbstractBeanFactory的getObjectForBeanInstance

最后调用父类的处理方法,会下判断name是不是FactoryBean自身的名字,如果是,就判断beanInstance 是不是FactoryBean类型的,是的话就直接返回,也就是说,要找的就是FactoryBean自身,而不是他创建的bean。如果不是FactoryBean自身的名字,类型也不是FactoryBean,那就普通的单例,直接返回。否则就是说明应该获取的是FactoryBean创建的bean。如果RootBeanDefinition 不为空的话,设置FactoryBean=true,否则就从FactoryBean的缓存中获取,如果获取到就直接返回,否则就要创建,然后返回。

    protected Object getObjectForBeanInstance(
    			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
    
    		if (BeanFactoryUtils.isFactoryDereference(name)) {//是否是FactoryBean名字的前缀
    			if (beanInstance instanceof NullBean) {
    				return beanInstance;
    			}
    			if (!(beanInstance instanceof FactoryBean)) {//不是FactoryBean的话名字有&会报异常
    				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
    			}
    			if (mbd != null) {
    				mbd.isFactoryBean = true;
    			}
    			return beanInstance;
    		}
    
    		if (!(beanInstance instanceof FactoryBean)) {//不是FactoryBean就直接返回
    			return beanInstance;
    		}
    		//创建FactoryBean中的bean
    		Object object = null;
    		if (mbd != null) {
    			mbd.isFactoryBean = true;
    		}
    		else {//从FactoryBean的缓存中获取
    			object = getCachedObjectForFactoryBean(beanName);
    		}
    		if (object == null) {
    
    			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
    
    			if (mbd == null && containsBeanDefinition(beanName)) {//mbd没定义,但是FactoryBean是有定义的,获取mbd
    				mbd = getMergedLocalBeanDefinition(beanName);
    			}
    			boolean synthetic = (mbd != null && mbd.isSynthetic());
    			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    		}
    		return object;
    	}

getCachedObjectForFactoryBean从缓存里获取

factoryBeanObjectCache就是FactoryBean创建的bean的缓存,创建一次后会进行缓存,下次直接拿。

    	@Nullable
    	protected Object getCachedObjectForFactoryBean(String beanName) {
    		return this.factoryBeanObjectCache.get(beanName);
    	}

getObjectFromFactoryBean创建bean

这里就是FactoryBean创建bean的过程。如果FactoryBean是单例,且已经创建出来了,先从缓存里获取看看,如果存在直接返回。如果不存在就进行doGetObjectFromFactoryBean创建,其实就是调用了getObject()获取对象。这里又做了一次从缓存中获取,感觉挺奇怪的,前面已经获取不存在了,这里怎么又能存在,其实是因为getObject()创建的时候可以自定义,可能有处理器处理,可能会对factoryBeanObjectCache进行设置,所以这里还要判断一次,如果存在的话,就应该获取存在的,而不是刚创建的,这样的话处理器才算是有扩展的功能,否则处理了也等于没用。如果没有缓存存在,判断是否是否需要处理,其实这里说的就是不是合成的对象!synthetic,比如AOPadvice通知就算是合成的,一般的对象都不合成的,如果需要处理,但是是正在创建中的单例,直接返回不处理,否则要进行处理器处理,最后放进缓存。如果是原型的话每次都创建一个新的。

    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);
    					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
    					if (alreadyThere != null) {
    						object = alreadyThere;
    					}
    					else {
    						if (shouldPostProcess) {//需要处理
    							if (isSingletonCurrentlyInCreation(beanName)) {//直接返回
    								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)) {//如果包含了FactoryBean,就将创建的对象缓存
    							this.factoryBeanObjectCache.put(beanName, object);
    						}
    					}
    				}
    				return object;
    			}
    		}
    		else {//FactoryBean是原型的话
    			Object object = doGetObjectFromFactoryBean(factory, beanName);
    			if (shouldPostProcess) {
    				try {
    					object = postProcessObjectFromFactoryBean(object, beanName);
    				}
    				catch (Throwable ex) {
    					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
    				}
    			}
    			return object;
    		}
    	}
doGetObjectFromFactoryBean

其实没别的东西,就是调用getObject()创建对象,如果返回null的话,就封装成一个NullBean

    private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
    			throws BeanCreationException {
    
    		Object object;
    		...
    		object = factory.getObject();//调用自定义的FactoryBean的getObject获取对象
    		...
    		if (object == null) {
    			if (isSingletonCurrentlyInCreation(beanName)) {//如果是正在创建的FactoryBean,还没能获得bean,就报异常
    				throw new BeanCurrentlyInCreationException(
    						beanName, "FactoryBean which is currently in creation returned null from getObject");
    			}
    			object = new NullBean();
    		}
    		return object;
    	}
beforeSingletonCreation和afterSingletonCreation

这个就是标记下,正在创建这个bean,创建处理完了就清除标记。

    	protected void beforeSingletonCreation(String beanName) {
    		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
    			throw new BeanCurrentlyInCreationException(beanName);//没有在排除范围里内且添加不成功,可能就是循环引用了
    		}
    	}
    
    	protected void afterSingletonCreation(String beanName) {
    	if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
    		throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
    	}
    }
postProcessObjectFromFactoryBean对创建出来的bean进行处理器处理

就是进行BeanPostProcessorpostProcessAfterInitialization处理,也就是可以扩展的地方。

    	@Override
    	protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
    		return applyBeanPostProcessorsAfterInitialization(object, beanName);
    	}
    	
    	@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;
    	}

实战例子

测试例子:

202309162312100847.png
没有设置原型:

202309162312105128.png

202309162312109119.png
设置了原型:

2023091623121143710.png

2023091623121184111.png

可见在FactoryBean上设置了@Scope("prototype")会影响创建的bean

果然讲细了没多少东西好讲,但是不讲清除直接跳过去等于没学什么,走马观花,到头来遇到问题还是得深入探究,学东西还是有点研究精神好。剩下的下篇继续吧。

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。

阅读全文