SpringloC容器的依赖注入源码解析(3),2024年最新Web毕业设计选题

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.

// 如果BeanDefinition为单例

if (mbd.isSingleton()) {

// 这里使用了一个匿名内部类,创建Bean实例对象,并且注册给所依赖的对象

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.isTraceEnabled()) {

logger.trace(“Failed to convert bean '” + name + “’ to required type '” +

ClassUtils.getQualifiedName(requiredType) + “'”, ex);

}

throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());

}

}

return (T) bean;

}

之前讨论了doGetBean里面从缓存获取bean的代码,doGetBean方法接下来的else处理Bean的scope为prototype或者单例模式但是缓存中还不存在bean的情况:

请添加图片描述

Spring同样为scope为prototype的Bean设计了一个缓存列表

if (isPrototypeCurrentlyInCreation(beanName)) {

throw new BeanCurrentlyInCreationException(beanName);

}

protected boolean isPrototypeCurrentlyInCreation(String beanName) {

Object curVal = this.prototypesCurrentlyInCreation.get();

return (curVal != null &&

(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));

}

相比单例的set,这里是ThreadLocal,只记录当前线程创建出来的scope为prototype的Bean,上面的if如果是true的话证明有循环依赖。

通过了循环依赖校验之后看容器是否存在父容器,如果存在且当前容器里没有包含此bean的BeanDefinition实例,尝试去从父类容器递归查询

请添加图片描述

为了防止之前的beanName已经被转换的不成样子,将&重新加上,再调用父类的doGetBean或者getBean方法,如果父类是AbstractBeanFactory,则调用doGetBean

如果当前容器里包含了此bean的BeanDefinition实例则继续执行

// typeCheckOnly 是用来判断调用 getBean() 是否仅仅是为了类型检查获取 bean,而不是为了创建Bean

if (!typeCheckOnly) {

// 如果不是仅仅做类型检查则是创建bean

markBeanAsCreated(beanName);

}

进入markBeanAsCreated方法里,

protected void markBeanAsCreated(String beanName) {

// 双重检查锁机制

if (!this.alreadyCreated.contains(beanName)) {

synchronized (this.mergedBeanDefinitions) {

if (!this.alreadyCreated.contains(beanName)) {

// Let the bean definition get re-merged now that we’re actually creating

// the bean… just in case some of its metadata changed in the meantime.

// 将原先合并之后的RootBeanDefinition的需要重新合并的状态设置为true

// 表示需要重新合并一遍,以防原数据的改动

clearMergedBeanDefinition(beanName);

// 将已经创建好的或者正在创建的Bean的名称加到alreadyCreated这个缓存中

this.alreadyCreated.add(beanName);

}

}

}

}

有一个双重锁检查机制,创建的Bean的名称加到alreadyCreated(类型Set)这个缓存中,在加入缓存之前需要将原先的MergedBeanDefinition设置上一个需要清除的标识符,目的是让后续从容器中获取BeanDefinition时重新合并子类和父类的BeanDefinition,这样就可以防止元数据被改动后,BeanDefinition还是按照原来的数据去创建

protected void clearMergedBeanDefinition(String beanName) {

RootBeanDefinition bd = this.mergedBeanDefinitions.get(beanName);

if (bd != null) {

bd.stale = true;

}

}

clearMergedBeanDefinition回去容器中获取RootBeanDefinition实例,然后把该实例需要重新合并的状态设为true(之前提到过,只要指定了parent属性,则两个BeanDefinition就合并成一个来使用)


回到doGetBean,接下来会调用getMergedLocalBeanDefinition方法来合并子类和父类的BeanDefinition,进入到该方法里:

protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {

// Quick check on the concurrent map first, with minimal locking.

RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);

if (mbd != null && !mbd.stale) {

return mbd;

}

return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));

}

先从mergedBeanDefinitions缓存里获取之前已经合并好的RootBeanDefinition实例,如果stale为true的话就会合并一遍BeanDefinition,随后返回。


回到doGetBean,获取到了BeanDefinition之后,就去对相关实例做合法性校验

checkMergedBeanDefinition(mbd, beanName, args);

进入到checkMergedBeanDefinition方法里:

protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args)

throws BeanDefinitionStoreException {

if (mbd.isAbstract()) {

throw new BeanIsAbstractException(beanName);

}

}

看一下RootBeanDefinition是否是抽象的。


回到doGetBean,尝试从BeanDefinition里获取显式的依赖关系,如果有depends-on的话就检查是否有循环依赖关系

请添加图片描述

如果没有循环依赖的话则会将相关的依赖关系注册上

registerDependentBean(dep, beanName);

public void registerDependentBean(String beanName, String dependentBeanName) {

String canonicalName = canonicalName(beanName);

synchronized (this.dependentBeanMap) {

// computeIfAbsent:若key对应的value为空,会将第二个参数的返回值存入并返回

// dependentBeanMap中存放着当前Bean被引用的Bean的集合

// 比如当前需要实例化的是Bean的名字是userInfo,userInfo中有个Human类型的属性human

// 那么就有human被userInfo引用的关系 human=[userInfo]

Set dependentBeans =

this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));

if (!dependentBeans.add(dependentBeanName)) {

return;

}

}

synchronized (this.dependenciesForBeanMap) {

Set dependenciesForBean =

this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));

dependenciesForBean.add(canonicalName);

}

}

先获取name,之后就进入两重注册,第一重注册往dependentBeanMap中写入键值对,key是被依赖的Bean名字,value是依赖他的Bean名字列表

第二重注册往dependenciesForBeanMap中写入键值对,键值对和上面正好是相反的


回到doGetBean,执行完显式依赖关系注册之后就会递归调用getBean(dep)来将依赖的bean创建出来,往后就是根据不同的scope进行不同的创建bean的操作了,分为Singleton、Prototype和其他。

除了Prototype是直接调用createBean(beanName, mbd, args)去创建Bean实例之外,scope=其他的将createBean封装到了一个匿名参数里

请添加图片描述

进入scope.get()方法

Object get(String name, ObjectFactory<?> objectFactory);

可见后面的匿名函数实现的是ObjectFactory的getObject方法,调用createBean方法去创建适配scope的实例。

下面主要分析scope = singleton的:

if (mbd.isSingleton()) {

// 这里使用了一个匿名内部类,创建Bean实例对象,并且注册给所依赖的对象

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.

// 显式从单例缓存中删除 bean实例

// 因为单例模式下为了解决循环依赖,可能它已经存在了,所以将其销毁

destroySingleton(beanName);

throw ex;

}

});

bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

}

进入getSingleton方法:

请添加图片描述

也是接收一个ObjectFactory对象然后实现其getObject方法。

进入createBean:

protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

throws BeanCreationException;

这是个抽象方法需要子类去实现。

再回到上面的getSingleton方法:

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {

Assert.notNull(beanName, “Bean name must not be null”);

synchronized (this.singletonObjects) {

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) {

// Has the singleton object implicitly appeared in the meantime ->

// if yes, proceed with it since the exception indicates that state.

singletonObject = this.singletonObjects.get(beanName);

if (singletonObject == null) {

throw ex;

}

}

catch (BeanCreationException ex) {

if (recordSuppressedExceptions) {

for (Exception suppressedException : this.suppressedExceptions) {

ex.addRelatedCause(suppressedException);

}

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数同学面临毕业设计项目选题时,很多人都会感到无从下手,尤其是对于计算机专业的学生来说,选择一个合适的题目尤为重要。因为毕业设计不仅是我们在大学四年学习的一个总结,更是展示自己能力的重要机会。

因此收集整理了一份《2024年计算机毕业设计项目大全》,初衷也很简单,就是希望能够帮助提高效率,同时减轻大家的负担。
img
img
img

既有Java、Web、PHP、也有C、小程序、Python等项目供你选择,真正体系化!

由于项目比较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频

如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)
img

}

catch (BeanCreationException ex) {

if (recordSuppressedExceptions) {

for (Exception suppressedException : this.suppressedExceptions) {

ex.addRelatedCause(suppressedException);

}

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数同学面临毕业设计项目选题时,很多人都会感到无从下手,尤其是对于计算机专业的学生来说,选择一个合适的题目尤为重要。因为毕业设计不仅是我们在大学四年学习的一个总结,更是展示自己能力的重要机会。

因此收集整理了一份《2024年计算机毕业设计项目大全》,初衷也很简单,就是希望能够帮助提高效率,同时减轻大家的负担。
[外链图片转存中…(img-sBWnUw6A-1712536115057)]
[外链图片转存中…(img-CDkLOWp8-1712536115058)]
[外链图片转存中…(img-vFMr9W6z-1712536115058)]

既有Java、Web、PHP、也有C、小程序、Python等项目供你选择,真正体系化!

由于项目比较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频

如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)
[外链图片转存中…(img-qLT5vtZo-1712536115059)]

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值