Spring源码解读之创建bean

本文章我们会解读一下Spring如何根据beanDefinition创建bean的;

代码入口:

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);applicationContext.refresh();

当spring执行refresh()这个方法进行上下文刷新时, 会进行非懒加载的bean的创建,创建非懒加载的bean的源码入口为:

finishBeanFactoryInitialization(beanFactory);

 该方法的具体实现:

/*** Finish the initialization of this context's bean factory,* initializing all remaining singleton beans.*/protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// Initialize conversion service for this context.// 如果BeanFactory中存在名字叫conversionService的Bean,则设置为BeanFactory的conversionService属性// ConversionService是用来进行类型转化的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 BeanFactoryPostProcessor// (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:// at this point, primarily for resolution in annotation attribute values.// 设置默认的占位符解析器  ${xxx}  ---keyif (!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.// 实例化非懒加载的单例BeanbeanFactory.preInstantiateSingletons();}

上述方法中,进行实例化非懒加载的单例bean的代码是

		// 实例化非懒加载的单例BeanbeanFactory.preInstantiateSingletons();

点击进入

DefaultListableBeanFactory.java的public void preInstantiateSingletons() 的方法;

@Overridepublic void preInstantiateSingletons() throws BeansException {if (logger.isTraceEnabled()) {logger.trace("Pre-instantiating singletons in " + this);}// Iterate over a copy to allow for init methods which in turn register new bean definitions.// While this may not be part of the regular factory bootstrap, it does otherwise work fine.List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// Trigger initialization of all non-lazy singleton beans...for (String beanName : beanNames) {// 获取合并后的BeanDefinitionRootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);//bd.isAbstract() 是不是抽象的BeanDefinition  一般是xml定义的  抽象的beanDefinition不会被创建if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {if (isFactoryBean(beanName)) {// 获取FactoryBean对象Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);if (bean instanceof FactoryBean) {FactoryBean<?> factory = (FactoryBean<?>) bean;boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,getAccessControlContext());}else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());}if (isEagerInit) {// 创建真正的Bean对象(getObject()返回的对象)getBean(beanName);}}}else {// 创建Bean对象getBean(beanName);}}}// 所有的非懒加载单例Bean都创建完了后// Trigger post-initialization callback for all applicable beans...for (String beanName : beanNames) {Object singletonInstance = getSingleton(beanName);if (singletonInstance instanceof SmartInitializingSingleton) {StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize").tag("beanName", beanName);SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {smartSingleton.afterSingletonsInstantiated();return null;}, getAccessControlContext());}else {smartSingleton.afterSingletonsInstantiated();}smartInitialize.end();}}}

此方法中 getBean(beanName);会创建bean;我们进入getBean()这个方法

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

然后我们进入doGetBean(name, null, null, false)这个方法,主要判断该bean的类型然后根据具体情况进行调用protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) 创建bean的实例。

/*** Return an instance, which may be shared or independent, of the specified bean.* @param name the name of the bean to retrieve* @param requiredType the required type of the bean to retrieve* @param args arguments to use when creating a bean instance using explicit arguments* (only applied when creating a new instance as opposed to retrieving an existing one)* @param typeCheckOnly whether the instance is obtained for a type check,* not for actual use* @return an instance of the bean* @throws BeansException if the bean could not be created*/@SuppressWarnings("unchecked")protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)throws BeansException {//对beanName做处理// name有可能是 &xxx 或者 xxx,如果name是&xxx,那么beanName就是xxx// name有可能传入进来的是别名,那么beanName就是idString beanName = transformedBeanName(name);Object beanInstance;// Eagerly check singleton cache for manually registered singletons.//先在单例池中去获取beanObject sharedInstance = getSingleton(beanName);//如果获取到了if (sharedInstance != null && args == null) {if (logger.isTraceEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference");}else {logger.trace("Returning cached instance of singleton bean '" + beanName + "'");}}// 如果获取到的bean(sharedInstance)是FactoryBean,需要对该bean进行进一步处理beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {	//如果在单例池中没有获取到bean// Fail if we're already creating this bean instance:// We're assumably within a circular reference.if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// Check if bean definition exists in this factory.BeanFactory parentBeanFactory = getParentBeanFactory();//containsBeanDefinition(beanName) 检测spring容器中有没有这个名字的bean//当前容器中没有找到,去父工厂找if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// Not found -> check parent.// &&&&xxx---->&xxxString nameToLookup = originalBeanName(name);if (parentBeanFactory instanceof AbstractBeanFactory) {return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);}else if (args != null) {// Delegation to parent with explicit args.return (T) parentBeanFactory.getBean(nameToLookup, args);}else if (requiredType != null) {// No args -> delegate to standard getBean method.return parentBeanFactory.getBean(nameToLookup, requiredType);}else {return (T) parentBeanFactory.getBean(nameToLookup);}}if (!typeCheckOnly) {markBeanAsCreated(beanName);}//JFR代码运行机制StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);try {if (requiredType != null) {beanCreation.tag("beanType", requiredType::toString);}//取出名字对应的合并后的beanDefinitionRootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);// 检查BeanDefinition是不是Abstract的,如果是Abstract  报错checkMergedBeanDefinition(mbd, beanName, args);// Guarantee initialization of beans that the current bean depends on.//创建当前bean之前,先需要创建@dependsOn里面的beanString[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {// dependsOn表示当前beanName所依赖的,当前Bean创建之前dependsOn所依赖的Bean必须已经创建好了for (String dep : dependsOn) {// beanName是不是被dep依赖了,如果是则出现了循环依赖if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}// dep被beanName依赖了,存入dependentBeanMap中,dep为key,beanName为valueregisterDependentBean(dep, beanName);// 创建所依赖的beantry {getBean(dep);}catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}}// Create bean instance.if (mbd.isSingleton()) {// 创建单例bean的逻辑: 先从缓存中拿,如果没有的,再创建该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;}});beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}else if (mbd.isPrototype()) {//创建原型bean的逻辑:直接创建对象// It's a prototype -> create a new instance.Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}else {//有作用域相关注解的bean  例如request、session等获取scope作用域注解信息String scopeName = mbd.getScope();if (!StringUtils.hasLength(scopeName)) {throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");}Scope scope = this.scopes.get(scopeName);if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");}try {  // session.getAttriute(beaName)  setAttri//类似非懒加载单例bean的创建,先从缓存中取,取不到,创建bean且放入缓存Object scopedInstance = scope.get(beanName, () -> {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}});beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);}catch (IllegalStateException ex) {throw new ScopeNotActiveException(beanName, scopeName, ex);}}}catch (BeansException ex) {beanCreation.tag("exception", ex.getClass().toString());beanCreation.tag("message", String.valueOf(ex.getMessage()));cleanupAfterBeanCreationFailure(beanName);throw ex;}finally {beanCreation.end();}}// 检查通过name所获得到的beanInstance的类型是否是requiredTypereturn adaptBeanInstance(name, beanInstance, requiredType);}

进入protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) ,这里会进行bean的实例化。

/*** Central method of this class: creates a bean instance,* populates the bean instance, applies post-processors, etc.* @see #doCreateBean*/@Overrideprotected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {if (logger.isTraceEnabled()) {logger.trace("Creating instance of bean '" + beanName + "'");}RootBeanDefinition mbdToUse = mbd;// Make sure bean class is actually resolved at this point, and// clone the bean definition in case of a dynamically resolved Class// which cannot be stored in the shared merged bean definition.// 马上就要实例化Bean了,确保beanClass被加载了,进行类加载Class<?> resolvedClass = resolveBeanClass(mbd, beanName);if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {mbdToUse = new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}// Prepare method overrides.try {mbdToUse.prepareMethodOverrides();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),beanName, "Validation of method overrides failed", ex);}try {// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.// 实例化前Object bean = resolveBeforeInstantiation(beanName, mbdToUse);if (bean != null) {return bean;}}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,"BeanPostProcessor before instantiation of bean failed", ex);}try {Object beanInstance = doCreateBean(beanName, mbdToUse, args);if (logger.isTraceEnabled()) {logger.trace("Finished creating instance of bean '" + beanName + "'");}return beanInstance;}catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {// A previously detected exception with proper bean creation context already,// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.throw ex;}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/224645.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用mock.js模拟数据

一、安装mock.js npm i mockjs 二、配置JSON文件 我们创建一个mock文件夹&#xff0c;用于存放mock相关的模拟数据和代码实现。 我们将数据全部放在xxx.json文件夹下&#xff0c;里面配置我们需要的JSON格式的数据。 注意&#xff1a;json文件中不要留有空格&#xff0c;否则…

系列二十四、Spring设计模式之策略模式

一、前言 对于我们Java开发人员来说&#xff0c;Spring框架的重要性不言而喻&#xff0c;可以说Java领域之所以发展这么壮大&#xff0c;生态这么丰富&#xff0c;功能这么强大&#xff0c;是离不开Spring以及由其衍生出来的各种子模块的&#xff0c;正是由它们共同奠定了JavaE…

好用的样式动画库集合(css、js)

文章目录 前言一、Animate.css二、Anime.js三、CSShake四、Hover.css五、AniJS六、Animista七、Tachyons-animate八、Sequence.js九、Infinite十、OBNOXIOUS.CSS十一、MOTION UI十二、Keyframes.app十三、AnimXYZ十四、Whirl十五、Hamburgers十六、Vivify十七、Magic Animation…

C++标准模板库 STL 简介(standard template library)

在 C 语言中&#xff0c;很多东西都是由我们自己去实现的&#xff0c;例如自定义数组&#xff0c;线程文件操作&#xff0c;排序算法等等&#xff0c;有些复杂的东西实现不好很容易留下不易发现的 bug。而 C为使用者提供了一套标准模板库 STL,其中封装了很多实用的容器&#xf…

网络工程师精华篇,50种网络故障及解决方法大集合

上午好&#xff0c;我的网工朋友。 做网络工程师&#xff0c;自然离不开网络&#xff0c;而日常工作中能搞多少大项目&#xff1f;最常见的其实还是网络故障的处理了。 怎么最高效地排查网络故障&#xff1f;怎么简单几招通网&#xff1f; 今天就从基础的入手&#xff0c;分…

QT QComBox实现模糊查询

一、概述 在Qt中&#xff0c;可以通过QComboBox和QLineEdit实现模糊查询的功能。模糊查询是指根据用户输入的文本&#xff0c;在下拉框的选项中进行模糊匹配&#xff0c;并动态地显示匹配的选项。 二、基础知识 1、QCompleter (1)QCompleter 是 Qt 框架中提供的一个用于自动…

巅峰对决 LlamaIndex 与 OpenAI API大比拼

我们进行了一项详尽的分析&#xff0c;比较了 OpenAI 助手 API 和 LlamaIndex 在 RAG 性能方面的差异。目的是使用Tonic Validate评估各种RAG系统&#xff0c;该系统是一个RAG评估和基准平台&#xff0c;同时使用开源工具tvalmetrics。本文中使用的所有代码和数据都可以在这里找…

GaussDB数据库SQL系列-触发器

目录 一、前言 二、触发器概念 三、GaussDB数据库中的触发器 1、语法格式 2、创建步骤 3、注意事项 4、附&#xff1a;表和视图上支持的触发器种类 四、GaussDB数据库中的示例 示例一、在GaussDB数据库中创建一个触发器&#xff0c;以便在插入新记录时自动将记录的创建…

Rocky Linux 9.3 为 PowerPC 64 位带回云和容器镜像

RHEL 克隆版 Rocky Linux 9.3 今天发布了&#xff0c;作为红帽企业 Linux 发行版 CentOS Stream 和 Red Hat Enterprise Linux 的免费替代版本&#xff0c;现在可供下载。 Rocky Linux 9.3 是在 Rocky Linux 9.2 发布 6 个月之后发布的&#xff0c;它带回了 PowerPC 64 位 Lit…

Vatee万腾的数字创新征途:vatee科技力量的独特奇点

在数字化的时代浪潮中&#xff0c;Vatee万腾如一颗耀眼的明星&#xff0c;以其独特的科技奇点引领着数字创新的征途。无论是在人工智能、大数据、云计算&#xff0c;还是智能化领域&#xff0c;Vatee万腾都展现出了与众不同的创新力量&#xff0c;为科技征途描绘了独一无二的奇…

【开源】基于Vue+SpringBoot的学校热点新闻推送系统

项目编号&#xff1a; S 047 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S047&#xff0c;文末获取源码。} 项目编号&#xff1a;S047&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 新闻类型模块2.2 新闻档案模块2.3 新…

[ CSS ] 内容超出容器后 以...省略

内容超出容器后 以…省略 当前效果 代码 <template><div class"box">有志者&#xff0c;事竟成&#xff0c;破釜沉舟&#xff0c;百二秦关终属楚; 有心人&#xff0c;天不负&#xff0c;卧薪尝胆&#xff0c;三千越甲可吞吴</div> </templa…