当前位置: 首页 > news >正文

腾讯云做网站怎么样十大开源软件

腾讯云做网站怎么样,十大开源软件,住房和城乡建设部2019年安全生产工作要点,温州公司网站开发这里我们采用手撕源码的方式#xff0c;开始探索spring boot源码中最有意思的部分-bean的生命周期#xff0c;也可以通过其中的原理理解很多面试以及工作中偶发遇到的问题。 springboot基于约定大于配置的思想对spring进行优化#xff0c;使得这个框架变得更加轻量化#…这里我们采用手撕源码的方式开始探索spring boot源码中最有意思的部分-bean的生命周期也可以通过其中的原理理解很多面试以及工作中偶发遇到的问题。 springboot基于约定大于配置的思想对spring进行优化使得这个框架变得更加轻量化集成各种starter组件时使其能够更加全面。 1、SpringApplication启动类的配置与软件包的反射加载 通常我们在建立一个新的spring boot项目时利用idea脚手架生成模板内部会自带一个标注有SpringApplication注解的启动类如下所示 /*** author : spring* {code description:}* {code date} : 2024/2/4* {code modified} By: spring* {code project:} spring-plus*/ SpringApplication(scanBeanPackagePath com/hlc/springplus/test) public class ApplicationStarter {public static void main(String[] args) {ApplicationContext applicationContext new DefaultApplicationContext(ApplicationStarter.class);TestBean contextBean (TestBean) applicationContext.getBean(test);contextBean.test();} } 由于本文的代码全部都是手撕所以会与spring boot的源码有所不同个人主义完美凸显。 言回正传用过spring boot的人都知道它主要的特色基础是它的“容器”的概念我们可以通过配置文件、注解、导入以及反射实例化后调用通用应用上下文注入的方式将我们的bean交给spring容器管理那么这里启动类启动后“容器”是怎么识别出我们标准或配置的bean信息同时将其实例化、配置属性、配置名称.....的呢 那么下面就是一个过程 获取启动类上标注注解中的包路径值 SpringApplication annotation appconfig.getAnnotation(SpringApplication.class);String beanPackagePath annotation.scanBeanPackagePath(); String path beanPackagePath.replace(., /); 这里的path就是我们实际的包路径为什么需要将.替换城/呢实际上我们配置的包路径是软件包中的相对路径并不是Resource获取时规定的路径格式。 获取当前类的类加载器并根据路径加载URL获取文件 ClassLoader classLoader DefaultApplicationContext.class.getClassLoader();URL resource classLoader.getResource(path);File file new File(resource.getFile()); DefaultApplicationContext就是我当前类的名称后续串完全部的流程会将全部的代码挂出的这里的类加载器获取资源的方式是比较常用的。 需要注意的是这里拿到的file有可能是文件夹也可能是文件。 通过文件夹或文件夹获取字节码 for (File item : files) {int begin item.getAbsolutePath().indexOf(com);int end item.getAbsolutePath().indexOf(.);String className item.getAbsolutePath().substring(begin, end).replace(\\, .);try {Class? clazz Class.forName(className);if (clazz.isAnnotationPresent(Component.class)) {beanClazzList.add(clazz);//收集后置处理器意图是收集后置处理器而不是收集bean对象if (BeanPostprocessor.class.isAssignableFrom(clazz)) {beanPostprocessorList.add((BeanPostprocessor) clazz.getDeclaredConstructor().newInstance());}}} catch (Exception e) {throw new RuntimeException(e.getMessage());} } 上面的类路径获取方式以及判断字节码是否实现了接口BeanPostprocessor的判断、字节码是否标注了注解Component的判断都是比较常用的方法。 那么通过此三步就将全部需要加载的字节码文件都获取到我们的成员变量beanClazzList列表中去了。 2、ApplicationContext接口的定义以及相关注解的配置 虽然我们解决了待加载bean的字节码列表的收集问题但是spring boot的容器我们还没有加载出来也没有实现相关注解的配置注解标注了bean的身份、名称、类型、加载方式、加载条件、加载顺序、依赖关系等。 ApplicationContext接口的定义 public interface ApplicationContext extends BeanFactory {Object getBean(String beanName);T void registerBean(T bean, ClassT clazz, String name); } ApplicationContext接口的释义是“应用上下文”在计算机科学中上下文表示进程在执行过程中系统内部的资源情况与中断向量表的记录情况总之代表的是进程所处的逻辑环境。这里顾名思义ApplicationContext代表的也自然就是bean所处的环境。也就是我们口中的spring boot的容器。 对于基本的ApplicationContext能力而言它应当具备获取bean对象与注册bean对象的能力。所以这里定义的两个基础能力接口。在考虑如何实现它之前我们还需要配置以下bean相关的其他注解 组件注解标注类型为bean组件 Retention(RetentionPolicy.RUNTIME) Target({ElementType.TYPE}) public interface Component {String name() default ; } 注入注解标注为某类型注入某bean的属性值 Target(ElementType.FIELD) Retention(RetentionPolicy.RUNTIME) public interface AutoWired {String value() default ; } 作用域注解标注单例、原型等生存周期的bean类型 Target({ElementType.TYPE, ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) public interface Scope {String value(); } 懒加载注解标注即用即加载还是立刻加载 Target({ElementType.TYPE, ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) public interface Lazy { } 初始化方法注解标注bean的初始化方法 Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) public interface InitBeanMethod { } 3、实现ApplicationContext接口与bean加载原理 上述我们定义了相关接口与注解接下来我们实现容器上下文接口以及描述bean是如何加载到容器内部管理的。 那么这里我们就先将实现ApplicationContext接口的DefaultApplicationContext.java代码放在下方 public class DefaultApplicationContext implements ApplicationContext {private final Class? appconfig;private ListClass? beanClazzList new LinkedList();private MapString, Object singletonBeanMap new ConcurrentHashMap();private MapString, BeanDefinition beanDefinitionMap new ConcurrentHashMap();private ListBeanPostprocessor beanPostprocessorList new LinkedList();public DefaultApplicationContext(Class? appconfig) {this.appconfig appconfig;//1、扫描启动类注解的字节码列表scanBeansByPackage(beanClazzList);//2、注册bean的BeanDefinition初始配置信息initBeanDefinition(beanClazzList, beanDefinitionMap);//3、实例化单例bean并存入map中instanceSingletonBeans(beanDefinitionMap, singletonBeanMap);}Overridepublic Object getBean(String beanName) {BeanDefinition beanDefinition beanDefinitionMap.get(beanName);if (null ! beanDefinition prototype.equals(beanDefinition.getScope())) {try {return beanDefinition.getBeanClazz().getDeclaredConstructor().newInstance();} catch (InstantiationException | IllegalAccessException | InvocationTargetException |NoSuchMethodException e) {throw new RuntimeException(e.getMessage());}}return singletonBeanMap.get(beanName);}Overridepublic T void registerBean(T bean, ClassT clazz, String name) {singletonBeanMap.put(name, bean);}/*** 扫描bean的字节码列表** param beanClazzList bean的字节码列表(待填充)*/protected void scanBeansByPackage(ListClass? beanClazzList) {if (null ! appconfig appconfig.isAnnotationPresent(SpringApplication.class)) {SpringApplication annotation appconfig.getAnnotation(SpringApplication.class);if (null ! annotation) {String beanPackagePath annotation.scanBeanPackagePath();String path beanPackagePath.replace(., /);ClassLoader classLoader DefaultApplicationContext.class.getClassLoader();URL resource classLoader.getResource(path);if (resource ! null) {File file new File(resource.getFile());if (file.isDirectory()) {File[] files file.listFiles();if (files ! null) {for (File item : files) {loadAndFilterBeanClazzes(beanClazzList, item);}}} else {loadAndFilterBeanClazzes(beanClazzList, file);}}} else {throw new RuntimeException(Annotation SpringApplication is not exist);}} else {throw new RuntimeException(Annotation SpringApplication is not exist and appconfig is null);}}/*** 加载bean的字节码列表并过滤** param beanClazzList bean的字节码列表(待填充)* param item 文件或文件夹*/private void loadAndFilterBeanClazzes(ListClass? beanClazzList, File item) {int begin item.getAbsolutePath().indexOf(com);int end item.getAbsolutePath().indexOf(.);String className item.getAbsolutePath().substring(begin, end).replace(\\, .);try {Class? clazz Class.forName(className);if (clazz.isAnnotationPresent(Component.class)) {beanClazzList.add(clazz);//收集后置处理器意图是收集后置处理器而不是收集bean对象if (BeanPostprocessor.class.isAssignableFrom(clazz)) {beanPostprocessorList.add((BeanPostprocessor) clazz.getDeclaredConstructor().newInstance());}}} catch (Exception e) {throw new RuntimeException(e.getMessage());}}/*** 注册bean的BeanDefinition初始配置信息** param beanClazzList bean的字节类型列表* param beanDefinitionMap bean的BeanDefinition初始配置信息池子*/private void initBeanDefinition(ListClass? beanClazzList, MapString, BeanDefinition beanDefinitionMap) {if (null ! beanClazzList !beanClazzList.isEmpty()) {for (Class? clazz : beanClazzList) {BeanDefinition beanDefinition new BeanDefinition();Component component clazz.getAnnotation(Component.class);Scope scope clazz.getAnnotation(Scope.class);Lazy lazy clazz.getAnnotation(Lazy.class);beanDefinition.setBeanClazz(clazz);beanDefinition.setLazy(null ! lazy);beanDefinition.setScope(null ! scope ? scope.value() : prototype);String beanName component.name();if (beanName.isEmpty()) {beanName clazz.getSimpleName();}beanDefinitionMap.put(beanName, beanDefinition);}}}/*** 实例化单例bean** param beanDefinitionMap bean定义信息* param singletonBeanMap 单例bean池子*/private void instanceSingletonBeans(MapString, BeanDefinition beanDefinitionMap, MapString, Object singletonBeanMap) {if (null ! beanDefinitionMap !beanDefinitionMap.isEmpty()) {for (Class? clazz : beanDefinitionMap.values().stream().map(BeanDefinition::getBeanClazz).toList()) {if (clazz.isAnnotationPresent(Scope.class) prototype.equals(clazz.getAnnotation(Scope.class).value())) {continue;}if (!clazz.isAnnotationPresent(Lazy.class)) {//实例化beantry {Component component clazz.getAnnotation(Component.class);String beanName component.name();if (null beanName || beanName.isEmpty()) {beanName clazz.getSimpleName();}//1、实例化beanObject newInstance clazz.getDeclaredConstructor().newInstance();//2、属性填充attributeAutoWiredPadding(clazz, newInstance);//3、aware能力透传awareBeanInstancePadding(newInstance);//4、初始化//4.1、后置处理器 初始化前执行for (BeanPostprocessor beanPostprocessor : beanPostprocessorList) {newInstance beanPostprocessor.beforeInitialization(newInstance, beanName);}//4.2、初始化bean执行//检查是否实现初始化Bean的接口initializeBeanInstancePadding(newInstance);//检查是否配置过init方法initBeanMethodInstancePadding(newInstance);//4.3、后置处理器能力 初始化后执行for (BeanPostprocessor beanPostprocessor : beanPostprocessorList) {newInstance beanPostprocessor.afterInitialization(newInstance, beanName);}singletonBeanMap.put(beanName, newInstance);} catch (InvocationTargetException | NoSuchMethodException | InstantiationException |IllegalAccessException e) {throw new RuntimeException(e.getMessage());}}}}}/*** bean的属性填充** param beanClazz bean的字节类型* param newInstance 实例化的bean*/private void attributeAutoWiredPadding(Class? beanClazz, Object newInstance) {if (null ! beanClazz) {Field[] fields beanClazz.getDeclaredFields();for (Field field : fields) {if (field.isAnnotationPresent(AutoWired.class)) {field.setAccessible(true);Class? declaringClass field.getType();AutoWired autoWired field.getAnnotation(AutoWired.class);String name autoWired.value();if (null name || name.isEmpty()) {name declaringClass.getSimpleName();}Object fieldBean singletonBeanMap.get(name);if (null fieldBean) {ListClass? beanClazzList new LinkedList();beanClazzList.add(declaringClass);initBeanDefinition(beanClazzList, beanDefinitionMap);MapString, BeanDefinition definitionMap new HashMap();definitionMap.put(name, beanDefinitionMap.get(name));instanceSingletonBeans(definitionMap, singletonBeanMap);try {field.set(newInstance, singletonBeanMap.get(name));} catch (IllegalAccessException e) {throw new RuntimeException(e.getMessage());}} else {try {field.set(newInstance, fieldBean);} catch (IllegalAccessException e) {throw new RuntimeException(e.getMessage());}}}}}}/*** bean的Aware接口的实现类填充** param bean bean实例对象*/private void awareBeanInstancePadding(Object bean) {if (null ! bean) {if (bean instanceof Aware) {if (bean instanceof ApplicationContextAware) {((ApplicationContextAware) bean).setApplicationContext(this);}if (bean instanceof BeanNameAware) {((BeanNameAware) bean).setBeanName();}}}}/*** bean的初始化方法填充** param bean 实例化的bean*/private void initializeBeanInstancePadding(Object bean) {if (null ! bean) {if (bean instanceof InitializingBean) {((InitializingBean) bean).afterPropertiesSet();}}}/*** bean的初始化方法填充** param newInstance 实例化的bean*/private void initBeanMethodInstancePadding(Object newInstance) {if (null ! newInstance) {Method[] methods newInstance.getClass().getDeclaredMethods();for (Method method : methods) {if (method.isAnnotationPresent(InitBeanMethod.class)) {method.setAccessible(true);try {method.invoke(newInstance);} catch (IllegalAccessException | InvocationTargetException e) {throw new RuntimeException(e.getMessage());}}}}}private void sortBeanInstanceClazzList() {} }这里我们着重描述一下关于bean加载原理的这一块代码 private void instanceSingletonBeans(MapString, BeanDefinition beanDefinitionMap, MapString, Object singletonBeanMap) {if (null ! beanDefinitionMap !beanDefinitionMap.isEmpty()) {for (Class? clazz : beanDefinitionMap.values().stream().map(BeanDefinition::getBeanClazz).toList()) {if (clazz.isAnnotationPresent(Scope.class) prototype.equals(clazz.getAnnotation(Scope.class).value())) {continue;}if (!clazz.isAnnotationPresent(Lazy.class)) {//实例化beantry {Component component clazz.getAnnotation(Component.class);String beanName component.name();if (null beanName || beanName.isEmpty()) {beanName clazz.getSimpleName();}//1、实例化beanObject newInstance clazz.getDeclaredConstructor().newInstance();//2、属性填充attributeAutoWiredPadding(clazz, newInstance);//3、aware能力透传awareBeanInstancePadding(newInstance);//4、初始化//4.1、后置处理器 初始化前执行for (BeanPostprocessor beanPostprocessor : beanPostprocessorList) {newInstance beanPostprocessor.beforeInitialization(newInstance, beanName);}//4.2、初始化bean执行//检查是否实现初始化Bean的接口initializeBeanInstancePadding(newInstance);//检查是否配置过init方法initBeanMethodInstancePadding(newInstance);//4.3、后置处理器能力 初始化后执行for (BeanPostprocessor beanPostprocessor : beanPostprocessorList) {newInstance beanPostprocessor.afterInitialization(newInstance, beanName);}singletonBeanMap.put(beanName, newInstance);} catch (InvocationTargetException | NoSuchMethodException | InstantiationException |IllegalAccessException e) {throw new RuntimeException(e.getMessage());}}}}} 到这里我们已经了解在获取待加载bean的字节码列表之后我们需要将bean的配置信息存储到我们的beanDefinitionMap中再根据beanDefinitionMap将其中的单例bean信息加载成一个个bean放入单例bean map中这里的存储key统一都是beanName。 看以上代码我们不难分析出通过bean配置信息加载bean的过程中一个bean需要经过6步周期性工作才会被放入容器中给我们使用。以下是图示
http://www.zqtcl.cn/news/144192/

相关文章:

  • 做网站的优势有哪些wordpress 一直崩溃
  • 长沙交互网站设计服务商优秀的网页网站设计
  • android 旅游网站开发有哪些做伦敦金的网站
  • 物流网站系统php源码seo课程多少钱
  • 手机 网站品牌网站建设 d磐石网络
  • 免费用搭建网站珠海住房和建设局网站
  • 天津做胎儿鉴定网站广州古德室内设计有限公司logo
  • 做爰的最好看的视频的网站简洁型网页
  • 网站一直显示建设中网页制作工具程
  • 苏州seo网站管理网站后台更新后主页没有变化
  • 上海网站公司电话中国电子信息网
  • 合作网站seo在哪里建网站免费
  • 需求网站自动发卡网站开发
  • 用asp做网站span电子商务网站建设的教案
  • 厦门市住房建设网站音乐主题wordpress
  • 小说网站开发文档建站公司用wordpress
  • 自己做手机版网站制作佛山网站建设企划动力
  • 鄂州建设工程造价信息管理网站wordpress 3.9 编辑文章 固定链接 不能编辑
  • asp网站的安全性织梦移动端网站建设
  • 大网站的二级域名哪些平台可以发布产品
  • 旅游网站开发说明书怎么做好销售
  • 网站app生成器天河网站建设服务
  • 南京移动网站建设哪里强新网站建设都需要哪些
  • .net网站制作wordpress配置多语言包
  • 上海源码网站建设公司做短视频的网站都有哪些
  • 网络推广公司联系昔年下拉网络优化seo
  • 网站开发语言识别网站众筹该怎么做
  • 长春做网站公司长春seo公司云主机和云服务器的区别
  • 打开网站乱码怎么做网件路由器登陆网址
  • wordpress 怎么删除主题seo神马网站推广器