Spring框架Ioc容器加载流程及Bean的生命周期源码分析

abd.setInstanceSupplier(instanceSupplier);

ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);

abd.setScope(scopeMetadata.getScopeName());

String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

if (qualifiers != null) {

for (Class<? extends Annotation> qualifier : qualifiers) {

if (Primary.class == qualifier) {

abd.setPrimary(true);

}

else if (Lazy.class == qualifier) {

abd.setLazyInit(true);

}

else {

abd.addQualifier(new AutowireCandidateQualifier(qualifier));

}

}

}

for (BeanDefinitionCustomizer customizer : definitionCustomizers) {

customizer.customize(abd);

}

BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);

definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);

}

到这里,就是到了IoC容器的核心代码了

从上往下依次是

AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);

这个里面两个动作

this.setBeanClass(beanClass);

this.metadata = new StandardAnnotationMetadata(beanClass, true);

作用就是将注解的相关信息,设置到我们的AnnotatedGenericBeanDefinition对象里面

if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {

return;

}

这个是判断是否有条件注入,如果有判断到这个注解,就不将其注入到IoC容器中

abd.setInstanceSupplier(instanceSupplier);

这个的作用为:设置回调

ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);

abd.setScope(scopeMetadata.getScopeName());

这里判断你是否加了@Scope这个注解,默认情况下为单例

可以点进去看看源码

@Override

public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {

ScopeMetadata metadata = new ScopeMetadata();

if (definition instanceof AnnotatedBeanDefinition) {

AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;

AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(

annDef.getMetadata(), this.scopeAnnotationType);

if (attributes != null) {

metadata.setScopeName(attributes.getString(“value”));

ScopedProxyMode proxyMode = attributes.getEnum(“proxyMode”);

if (proxyMode == ScopedProxyMode.DEFAULT) {

proxyMode = this.defaultProxyMode;

}

metadata.setScopedProxyMode(proxyMode);

}

}

return metadata;

}

接下来

String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

@Override

public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {

if (definition instanceof AnnotatedBeanDefinition) {

String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);

if (StringUtils.hasText(beanName)) {

// Explicit bean name found.

return beanName;

}

}

// Fallback: generate a unique default bean name.

return buildDefaultBeanName(definition, registry);

}

@Nullable

protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {

AnnotationMetadata amd = annotatedDef.getMetadata();

Set types = amd.getAnnotationTypes();

String beanName = null;

for (String type : types) {

AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);

if (attributes != null && isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) {

Object value = attributes.get(“value”);

if (value instanceof String) {

String strVal = (String) value;

if (StringUtils.hasLength(strVal)) {

if (beanName != null && !strVal.equals(beanName)) {

throw new IllegalStateException("Stereotype annotations suggest inconsistent " +

“component names: '” + beanName + “’ versus '” + strVal + “'”);

}

beanName = strVal;

}

}

}

}

return beanName;

}

这里,首先判断你是否是注解的方式注入,判断是否有传beanName,如果没有就给一个默认的beanName,默认首字母小写的类名。

具体的为:determineBeanNameFromAnnotation()方法就是看一下你有没有自己设置bean的名称

如果没有,就走buildDefaultBeanName(definition, registry);这个方法给你设置一个默认的bean名称。

接下来

AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {

processCommonDefinitionAnnotations(abd, abd.getMetadata());

}

static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {

AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);

if (lazy != null) {

abd.setLazyInit(lazy.getBoolean(“value”));

}

else if (abd.getMetadata() != metadata) {

lazy = attributesFor(abd.getMetadata(), Lazy.class);

if (lazy != null) {

abd.setLazyInit(lazy.getBoolean(“value”));

}

}

if (metadata.isAnnotated(Primary.class.getName())) {

abd.setPrimary(true);

}

AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);

if (dependsOn != null) {

abd.setDependsOn(dependsOn.getStringArray(“value”));

}

if (abd instanceof AbstractBeanDefinition) {

AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;

AnnotationAttributes role = attributesFor(metadata, Role.class);

if (role != null) {

absBd.setRole(role.getNumber(“value”).intValue());

}

AnnotationAttributes description = attributesFor(metadata, Description.class);

if (description != null) {

absBd.setDescription(description.getString(“value”));

}

}

}

这里就是判断下你是否带上了@ Lazy、@ Primary、@ DependsOn、@ Role、@ Description这些注解,如果带上了,进行一些相应的处理。

@ DependsOn:加载优先级

@ Role:有没有设置分类

往下

BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);

definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

这里为啥要用一个BeanDefinitionHolder呢,debug一下可以看到,BeanDefinitionHolder对象内部包括了

private final BeanDefinition beanDefinition;

private final String beanName;

@Nullable

private final String[] aliases;

由于beanDefinition中不包含beanName,无法注入到IoC容器中,所以会需要用BeanDefinitionHolder再给他包装有带一个beanName的对象。

最后

BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);

public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {

String beanName = definitionHolder.getBeanName();

registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

String[] aliases = definitionHolder.getAliases();

if (aliases != null) {

String[] var4 = aliases;

int var5 = aliases.length;

for(int var6 = 0; var6 < var5; ++var6) {

String alias = var4[var6];

registry.registerAlias(beanName, alias);

}

}

}

这里就是注册到IoC容器的动作了,可以看到这里首先会去获取beanName,也就说明了,为什么前面会需要带beanName这个节点。

这里的registry.registerBeanDefinition(),一共具有三个实现类:DefaultListableBeanFactory、GenericApplicationContext、SimpleBeanDefinitionRegistry。那到底是哪个实现类呢,其实再初始化this()里面,初始化父类的时候有一段源码如下。

public GenericApplicationContext() {

this.beanFactory = new DefaultListableBeanFactory();

}

可以看到beanFactory类型为DefaultListableBeanFactory

此时子类中this.registry = registry;

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {

Assert.notNull(registry, “BeanDefinitionRegistry must not be null”);

Assert.notNull(environment, “Environment must not be null”);

this.registry = registry;

this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

}

因此

this.reader = new AnnotatedBeanDefinitionReader(this);

里面的

private final BeanDefinitionRegistry registry;

即是前面父类给过来的DefaultListableBeanFactory实现类

所以现在代码走到了

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {

Assert.hasText(beanName, “Bean name must not be empty”);

Assert.notNull(beanDefinition, “BeanDefinition must not be null”);

if (beanDefinition instanceof AbstractBeanDefinition) {

try {

((AbstractBeanDefinition)beanDefinition).validate();

} catch (BeanDefinitionValidationException var9) {

throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, “Validation of bean definition failed”, var9);

}

}

BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);

if (oldBeanDefinition != null) {

if (!this.isAllowBeanDefinitionOverriding()) {

throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, “Cannot register bean definition [” + beanDefinition + “] for bean '” + beanName + “': There is already [” + oldBeanDefinition + “] bound.”);

}

if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {

if (this.logger.isWarnEnabled()) {

this.logger.warn(“Overriding user-defined bean definition for bean '” + beanName + “’ with a framework-generated bean definition: replacing [” + oldBeanDefinition + “] with [” + beanDefinition + “]”);

}

} else if (!beanDefinition.equals(oldBeanDefinition)) {

if (this.logger.isInfoEnabled()) {

this.logger.info(“Overriding bean definition for bean '” + beanName + “’ with a different definition: replacing [” + oldBeanDefinition + “] with [” + beanDefinition + “]”);

}

} else if (this.logger.isDebugEnabled()) {

this.logger.debug(“Overriding bean definition for bean '” + beanName + “’ with an equivalent definition: replacing [” + oldBeanDefinition + “] with [” + beanDefinition + “]”);

}

this.beanDefinitionMap.put(beanName, beanDefinition);

} else {

if (this.hasBeanCreationStarted()) {

synchronized(this.beanDefinitionMap) {

this.beanDefinitionMap.put(beanName, beanDefinition);

List updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);

updatedDefinitions.addAll(this.beanDefinitionNames);

updatedDefinitions.add(beanName);

this.beanDefinitionNames = updatedDefinitions;

if (this.manualSingletonNames.contains(beanName)) {

Set updatedSingletons = new LinkedHashSet(this.manualSingletonNames);

updatedSingletons.remove(beanName);

this.manualSingletonNames = updatedSingletons;

}

}

} else {

this.beanDefinitionMap.put(beanName, beanDefinition);

this.beanDefinitionNames.add(beanName);

this.manualSingletonNames.remove(beanName);

}

this.frozenBeanDefinitionNames = null;

}

if (oldBeanDefinition != null || this.containsSingleton(beanName)) {

this.resetBeanDefinition(beanName);

}

}

那么其实最后是通过

this.beanDefinitionMap.put(beanName, beanDefinition);

进行注册到IoC容器中,至此注册一些基本的信息到SpringIoC容器已经完成

最后到this.refresh();方法,主要分析其bean的生命周期流程,见下图

请添加图片描述

源码如下

public void refresh() throws BeansException, IllegalStateException {

synchronized(this.startupShutdownMonitor) {

this.prepareRefresh();

ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();

this.prepareBeanFactory(beanFactory);

try {

this.postProcessBeanFactory(beanFactory);

this.invokeBeanFactoryPostProcessors(beanFactory);

this.registerBeanPostProcessors(beanFactory);

this.initMessageSource();

this.initApplicationEventMulticaster();

this.onRefresh();

this.registerListeners();

this.finishBeanFactoryInitialization(beanFactory);

this.finishRefresh();

} catch (BeansException var9) {

if (this.logger.isWarnEnabled()) {

this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);

}

this.destroyBeans();

this.cancelRefresh(var9);

throw var9;

} finally {

this.resetCommonCaches();

}

}

}

bean的加载是从

// Instantiate all remaining (non-lazy-init) singletons.

finishBeanFactoryInitialization(beanFactory);

开始执行

进入这个方法

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {

// Initialize conversion service for this context.

if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&

beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {

beanFactory.setConversionService(

beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));

}

// Register a default embedded value resolver if no bean post-processor

// (such as a PropertyPlaceholderConfigurer bean) registered any before:

// at this point, primarily for resolution in annotation attribute values.

if (!beanFactory.hasEmbeddedValueResolver()) {

beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));

}

// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.

String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);

for (String weaverAwareName : weaverAwareNames) {

getBean(weaverAwareName);

}

// Stop using the temporary ClassLoader for type matching.

beanFactory.setTempClassLoader(null);

// Allow for caching all bean definition metadata, not expecting further changes.

beanFactory.freezeConfiguration();

// Instantiate all remaining (non-lazy-init) singletons.

beanFactory.preInstantiateSingletons();

}

进入beanFactory.preInstantiateSingletons();这个方法,这个方法中主要看到getBean()方法,因为当bean不存在的时候,该方法即会进行创建。

@Override

public Object getBean(String name) throws BeansException {

return doGetBean(name, null, null, false);

}

进入doGetBean方法,看到createBean()方法

try {

Object scopedInstance = scope.get(beanName, () -> {

beforePrototypeCreation(beanName);

try {

return createBean(beanName, mbd, args);

}

finally {

afterPrototypeCreation(beanName);

}

});

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

}

继续跟到doCreateBean方法

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

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

最后

这份《“java高分面试指南”-25分类227页1000+题50w+字解析》同样可分享给有需要的朋友,感兴趣的伙伴们可挑战一下自我,在不看答案解析的情况,测试测试自己的解题水平,这样也能达到事半功倍的效果!(好东西要大家一起看才香)

image

image

厂,18年进入阿里一直到现在。**

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-S7XeLNAu-1712113436721)]
[外链图片转存中…(img-Qb8dz5Fv-1712113436722)]
[外链图片转存中…(img-RYqr4JxS-1712113436722)]
[外链图片转存中…(img-pQEKnL0r-1712113436723)]
[外链图片转存中…(img-XdjAa9Pu-1712113436723)]
[外链图片转存中…(img-V3mnaYQz-1712113436724)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-mZ19ckk3-1712113436724)]

最后

这份《“java高分面试指南”-25分类227页1000+题50w+字解析》同样可分享给有需要的朋友,感兴趣的伙伴们可挑战一下自我,在不看答案解析的情况,测试测试自己的解题水平,这样也能达到事半功倍的效果!(好东西要大家一起看才香)

[外链图片转存中…(img-OW7YtHtg-1712113436724)]

[外链图片转存中…(img-VNnmxK5i-1712113436725)]

  • 16
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值