96SEO 2026-02-20 07:14 9
springboot基于约定大于配置的思想对spring进行优化#xff0c;使得这个框架变得更加轻量化#…这里我们采用手撕源码的方式开始探索spring

boot源码中最有意思的部分-bean的生命周期也可以通过其中的原理理解很多面试以及工作中偶发遇到的问题。
springboot基于约定大于配置的思想对spring进行优化使得这个框架变得更加轻量化集成各种starter组件时使其能够更加全面。
1、SpringApplication启动类的配置与软件包的反射加载
boot项目时利用idea脚手架生成模板内部会自带一个标注有SpringApplication注解的启动类如下所示
SpringApplication(scanBeanPackagePath
DefaultApplicationContext(ApplicationStarter.class);TestBean
applicationContext.getBean(test);contextBean.test();}
boot的人都知道它主要的特色基础是它的“容器”的概念我们可以通过配置文件、注解、导入以及反射实例化后调用通用应用上下文注入的方式将我们的bean交给spring容器管理那么这里启动类启动后“容器”是怎么识别出我们标准或配置的bean信息同时将其实例化、配置属性、配置名称.....的呢
appconfig.getAnnotation(SpringApplication.class);String
annotation.scanBeanPackagePath();
这里的path就是我们实际的包路径为什么需要将.替换城/呢实际上我们配置的包路径是软件包中的相对路径并不是Resource获取时规定的路径格式。
DefaultApplicationContext.class.getClassLoader();URL
classLoader.getResource(path);File
DefaultApplicationContext就是我当前类的名称后续串完全部的流程会将全部的代码挂出的这里的类加载器获取资源的方式是比较常用的。
item.getAbsolutePath().indexOf(com);int
item.getAbsolutePath().indexOf(.);String
item.getAbsolutePath().substring(begin,
(clazz.isAnnotationPresent(Component.class))
{beanClazzList.add(clazz);//收集后置处理器意图是收集后置处理器而不是收集bean对象if
(BeanPostprocessor.class.isAssignableFrom(clazz))
{beanPostprocessorList.add((BeanPostprocessor)
clazz.getDeclaredConstructor().newInstance());}}}
RuntimeException(e.getMessage());}
上面的类路径获取方式以及判断字节码是否实现了接口BeanPostprocessor的判断、字节码是否标注了注解Component的判断都是比较常用的方法。
那么通过此三步就将全部需要加载的字节码文件都获取到我们的成员变量beanClazzList列表中去了。
2、ApplicationContext接口的定义以及相关注解的配置
虽然我们解决了待加载bean的字节码列表的收集问题但是spring
boot的容器我们还没有加载出来也没有实现相关注解的配置注解标注了bean的身份、名称、类型、加载方式、加载条件、加载顺序、依赖关系等。
ApplicationContext接口的释义是“应用上下文”在计算机科学中上下文表示进程在执行过程中系统内部的资源情况与中断向量表的记录情况总之代表的是进程所处的逻辑环境。
这里顾名思义ApplicationContext代表的也自然就是bean所处的环境。
也就是我们口中的spring
对于基本的ApplicationContext能力而言它应当具备获取bean对象与注册bean对象的能力。
所以这里定义的两个基础能力接口。
在考虑如何实现它之前我们还需要配置以下bean相关的其他注解
Retention(RetentionPolicy.RUNTIME)
Retention(RetentionPolicy.RUNTIME)
Retention(RetentionPolicy.RUNTIME)
Retention(RetentionPolicy.RUNTIME)
Retention(RetentionPolicy.RUNTIME)
3、实现ApplicationContext接口与bean加载原理
上述我们定义了相关接口与注解接下来我们实现容器上下文接口以及描述bean是如何加载到容器内部管理的。
那么这里我们就先将实现ApplicationContext接口的DefaultApplicationContext.java代码放在下方
DefaultApplicationContext(Class?
appconfig;//1、扫描启动类注解的字节码列表scanBeansByPackage(beanClazzList);//2、注册bean的BeanDefinition初始配置信息initBeanDefinition(beanClazzList,
beanDefinitionMap);//3、实例化单例bean并存入map中instanceSingletonBeans(beanDefinitionMap,
singletonBeanMap);}Overridepublic
beanDefinitionMap.get(beanName);if
prototype.equals(beanDefinition.getScope()))
beanDefinition.getBeanClazz().getDeclaredConstructor().newInstance();}
RuntimeException(e.getMessage());}}return
singletonBeanMap.get(beanName);}Overridepublic
appconfig.isAnnotationPresent(SpringApplication.class))
appconfig.getAnnotation(SpringApplication.class);if
annotation.scanBeanPackagePath();String
DefaultApplicationContext.class.getClassLoader();URL
classLoader.getResource(path);if
{loadAndFilterBeanClazzes(beanClazzList,
{loadAndFilterBeanClazzes(beanClazzList,
loadAndFilterBeanClazzes(ListClass?
item.getAbsolutePath().indexOf(com);int
item.getAbsolutePath().indexOf(.);String
item.getAbsolutePath().substring(begin,
(clazz.isAnnotationPresent(Component.class))
{beanClazzList.add(clazz);//收集后置处理器意图是收集后置处理器而不是收集bean对象if
(BeanPostprocessor.class.isAssignableFrom(clazz))
{beanPostprocessorList.add((BeanPostprocessor)
clazz.getDeclaredConstructor().newInstance());}}}
RuntimeException(e.getMessage());}}/***
bean的BeanDefinition初始配置信息池子*/private
clazz.getAnnotation(Component.class);Scope
clazz.getAnnotation(Scope.class);Lazy
clazz.getAnnotation(Lazy.class);beanDefinition.setBeanClazz(clazz);beanDefinition.setLazy(null
lazy);beanDefinition.setScope(null
clazz.getSimpleName();}beanDefinitionMap.put(beanName,
instanceSingletonBeans(MapString,
beanDefinitionMap.values().stream().map(BeanDefinition::getBeanClazz).toList())
(clazz.isAnnotationPresent(Scope.class)
prototype.equals(clazz.getAnnotation(Scope.class).value()))
(!clazz.isAnnotationPresent(Lazy.class))
clazz.getAnnotation(Component.class);String
clazz.getSimpleName();}//1、实例化beanObject
clazz.getDeclaredConstructor().newInstance();//2、属性填充attributeAutoWiredPadding(clazz,
newInstance);//3、aware能力透传awareBeanInstancePadding(newInstance);//4、初始化//4.1、后置处理器
beanPostprocessor.beforeInitialization(newInstance,
beanName);}//4.2、初始化bean执行//检查是否实现初始化Bean的接口initializeBeanInstancePadding(newInstance);//检查是否配置过init方法initBeanMethodInstancePadding(newInstance);//4.3、后置处理器能力
beanPostprocessor.afterInitialization(newInstance,
beanName);}singletonBeanMap.put(beanName,
RuntimeException(e.getMessage());}}}}}/***
attributeAutoWiredPadding(Class?
beanClazz.getDeclaredFields();for
(field.isAnnotationPresent(AutoWired.class))
{field.setAccessible(true);Class?
field.getAnnotation(AutoWired.class);String
declaringClass.getSimpleName();}Object
LinkedList();beanClazzList.add(declaringClass);initBeanDefinition(beanClazzList,
HashMap();definitionMap.put(name,
beanDefinitionMap.get(name));instanceSingletonBeans(definitionMap,
RuntimeException(e.getMessage());}}
RuntimeException(e.getMessage());}}}}}}/***
awareBeanInstancePadding(Object
bean).setApplicationContext(this);}if
initializeBeanInstancePadding(Object
bean).afterPropertiesSet();}}}/***
initBeanMethodInstancePadding(Object
newInstance.getClass().getDeclaredMethods();for
(method.isAnnotationPresent(InitBeanMethod.class))
{method.setAccessible(true);try
RuntimeException(e.getMessage());}}}}}private
instanceSingletonBeans(MapString,
beanDefinitionMap.values().stream().map(BeanDefinition::getBeanClazz).toList())
(clazz.isAnnotationPresent(Scope.class)
prototype.equals(clazz.getAnnotation(Scope.class).value()))
(!clazz.isAnnotationPresent(Lazy.class))
clazz.getAnnotation(Component.class);String
clazz.getSimpleName();}//1、实例化beanObject
clazz.getDeclaredConstructor().newInstance();//2、属性填充attributeAutoWiredPadding(clazz,
newInstance);//3、aware能力透传awareBeanInstancePadding(newInstance);//4、初始化//4.1、后置处理器
beanPostprocessor.beforeInitialization(newInstance,
beanName);}//4.2、初始化bean执行//检查是否实现初始化Bean的接口initializeBeanInstancePadding(newInstance);//检查是否配置过init方法initBeanMethodInstancePadding(newInstance);//4.3、后置处理器能力
beanPostprocessor.afterInitialization(newInstance,
beanName);}singletonBeanMap.put(beanName,
RuntimeException(e.getMessage());}}}}}
到这里我们已经了解在获取待加载bean的字节码列表之后我们需要将bean的配置信息存储到我们的beanDefinitionMap中再根据beanDefinitionMap将其中的单例bean信息加载成一个个bean放入单例bean
看以上代码我们不难分析出通过bean配置信息加载bean的过程中一个bean需要经过6步周期性工作才会被放入容器中给我们使用。
以下是图示
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback