ApplicationContext.getBean源码解析

spring中有两种类型的Bean:一种是普通的JavaBean;另一种就是工厂Bean(FactoryBean),这两种Bean都受Spring的IoC容器管理,但它们之间却有一些区别。

 

普通的JavaBean不再多说,我们将其定义好,然后在配置文件中定义并配置其依赖关系,就可以通过IoC容器的getBean获取到。

那么FactoryBean呢?

FactoryBean跟普通Bean不同,它是实现了FactoryBean<T>接口的Bean,

1.通过BeanFactory类的getBean方法直接获取到的并不是该FactoryBean的实例,而是该FactoryBean中方法getObject返回的对象。

2.但我们可以通过其它途径获取到该FactoryBean的实例,方法就是在通过getBean方法获取实例时在参数name前面加上“&”符号即可。

FactoryBean接口提供的方法如下:

public interface FactoryBean<T> {
	//获取FactoryBean初始化的Bean实例
	T getObject() throws Exception;
	//获取Bean实例的类型
	Class<?> getObjectType();
	//判断是否是单例模式
	boolean isSingleton();
}

 

通常会通过这种方式获取到容器中的bean:

ApplicationContext appCtx = new ClassPathXmlApplicationContext("applicationContext.xml");
appCtx.getBean("myFactoryBean");
appCtx.getBean("&myFactoryBean");

通过跟代码,会定位到org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)方法:

@Override
public Object getBean(String name) throws BeansException {
	return doGetBean(name, null, null, false);
}

doGetBean方法中,会调用getObjectForBeanInstance来获取给定的bean实例的对象,

protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
			throws BeansException {
		.........//省略部分代码
		bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		.........//省略部分代码
		return (T) bean;
	}

getObjectForBeanInstance方法在AbstractBeanFactory的getObjectForBeanInstance方法

获取给定bean实例的对象,对于FactoryBean,可以是bean实例本身,也可以是它创建的对象。

protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		// Don't let calling code try to dereference the factory if the bean isn't a factory.
		//如果bean name是以&开始的,会直接返回beanInstance
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			if (!(beanInstance instanceof FactoryBean)) {
				//beanInstance不是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.
			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());
                        //从给定的FactoryBean获取要公开的对象
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

其中BeanFactoryUtils.isFactoryDereference(name)源码如下,只是判断了开始是否是&开头

String FACTORY_BEAN_PREFIX = "&";

public static boolean isFactoryDereference(@Nullable String name) {
		return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
	}

getObjectFromFactoryBean方法如下,用来从FactoryBean中获取bean

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 {
			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;
		}
	}

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用内容和,可以得出getBean(String name)和getBean(Class<T> type)的不同之处是前者获取的对象需要进行类型转换,而后者获取的对象无需类型转换。 根据引用内容,可以知道在Spring容器中,可以通过调用ApplicationContextgetBean方法来获取已初始化的bean。而Object bean = applicationContext.getBean则是调用getBean方法来获取一个名为bean的对象,并将其赋值给一个Object类型的变量。 请注意,这里的"bean"是一个占位符,实际上应该是一个具体的bean名称或bean的类型参数。因此,如果要获取一个名为"myBean"的bean对象,代码可能类似于:Object bean = applicationContext.getBean("myBean");或者通过类型获取对象,代码可能类似于:Object bean = applicationContext.getBean(MyBean.class)。具体使用哪种方式取决于你想要获取的bean的标识方式。 总之,Object bean = applicationContext.getBean是用来获取Spring容器中已初始化的bean对象的方法,具体的bean名称或类型参数需要根据实际情况进行指定。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [ApplicationContextgetBean方法详解](https://blog.csdn.net/weixin_30625691/article/details/99525303)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值