Spring源码(3) Spring IoC之BeanFactory创建bean和获取bean
ApplicationContext 和 BeanFactory
可以先简单了解下 ApplicationContext 和 BeanFactory。
详情见: https://blog.csdn.net/sinat_32502451/article/details/140247662
getBean() 代码示例
首先看代码示例,调试一下。
代码详情见: https://blog.csdn.net/sinat_32502451/article/details/140155044
public class MySpring {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("classpath*:mySpring.xml");
//在 getBean 这一行,打个断点
Person person = context.getBean("person", Person.class);
System.out.println("=======>"+ person.getName());
}
}
BeanFactory 的 getBean() 源码:
public interface BeanFactory {
//根据 bean 的名称,返回 bean对象.
Object getBean(String name) throws BeansException;
//根据 bean 名称,以及 匹配bean的类型,返回 bean对象.
<T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
}
bean 的作用域:
BeanFactory 中这两个方法,用于判断 bean 的作用域。
//作用域是否为单例模式?如果是, 每次调用 getBean()方法都会返回同一个对象。
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
//作用域是否为原型模式?如果是, 每次调用 getBean()方法都会返回不同的对象。
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
bean 对象的三级缓存:
bean 对象主要放在 map 里面,map 作为缓存。map 的key 是 bean对象的名称, value 是 bean 对象或者对象工厂。
Spring 使用了 三级缓存。
详情见:org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
/** 第一级缓存,里面放置的是已经实例化好的单例对象 */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** 第二级缓存,里面存放的是提前曝光的单例对象 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** 第三级缓存,里面存放的是将要被实例化的对象的对象工厂 */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
添加 bean 对象到缓存中 :
- 创建 bean 对象,添加 到缓存的具体方法:
重点看下这几个方法。
org.springframework.context.support.AbstractApplicationContext#refresh
----> org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization
----> org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
----> org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
----> org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
----> org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
接下来会 实例化bean :
-----> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
-----> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
初始化 bean:
-----> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
添加 bean 对象到缓存:
----> org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#addSingleton
获取 bean对象:
----> org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
----> org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
----> org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
可以看到 实例化bean 、初始化 bean、 获取 bean对象, 都调用了 getBean() 方法。
getBean() 的具体实现:
重点看 getSingleton() 方法 和 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;
// 检查单例缓存中是否有手动注册的单例
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 {
// 如果我们已经在创建这个bean实例,则失败
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
//检查此工厂中是否存在bean定义
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 保证初始化当前bean所依赖的bean
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);
}
}
}
// 判断是否单例模式
if (mbd.isSingleton()) {
//获取单例模式的 bean,并添加到缓存中。这里可以重点看看。
sharedInstance = getSingleton(beanName, () -> {
try {
//创建bean实例。。重点看看。
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// 从单例缓存中删除实例
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// 如果是原型模式,就创建一个新的实例
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;
}
}
// 检查所需的类型是否与实际bean实例的类型匹配
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;
}
创建 bean 对象:
关键看 实例化 bean 、 初始化 bean 。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 实例化 bean。 核心。
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), 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.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
// 初始化bean。。核心。重点看看。
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
初始化bean:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
- 获取单例对象:
根据 bean 名称,返回已经注册的单例对象,
如果没有注册,则创建并注册一个新对象。
/**
* 根据 bean 名称,返回已经注册的单例对象,如果没有注册,则创建并注册一个新对象。
*/
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
//加同步锁
synchronized (this.singletonObjects) {
//根据 bean 名称,返回已经注册的单例对象
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 {
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
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) {
//前面介绍过, 如果是新的单例对象,此处将 bean 添加到 缓存中
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
- addSingleton() 方法:
如下, 将 bean 添加到 缓存中 :
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//添加到缓存中。beanName值类似 上面的对象名"person"
//singletonObject类似具体的对象 Person(age=1, name=Tom, fullName=null, dateOfBirth=null)
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2023-07-11 SpringBoot使用@PropertySource读取 properties 配置
2023-07-11 maven/ SpringBoot 配置profile指定环境
2022-07-11 Intellij Idea的数据库工具 DataGrip
2018-07-11 如何阅读一个Web项目 【转载】