一、我也曾后悔过踏入程序员这一职业

相信大家考上大学时应该都有面临过选专业这一道难题吧,我同样没有避免,但是我还是算比较果断的,因为我从初中开始就对计算机感兴趣,然后就很佛的报了计算机专业,大学时,我对这个专业还是一直抱有很大的希望的。

直到毕业工作三年了,发现现在的工作只有加不完的班,敲不完的代码,增删改查,完全失去了灵魂,和我当初的初心完全是相反的,再三考虑后我辞职去面试了一直向往的企业“阿里”,但无奈一面就被刷了下来,那段时间,我真的自闭到后悔自己踏入这个行业。

二、Spring生命周期的大胆猜测

这里分享一个阅读源码的小技巧:捉大放小,连蒙带猜!8字真言,我们在阅读源码过程中,因为你要知道,每一个被开源出来的优秀框架,其源码的体系都是极其庞大复杂的,我们不能面面俱到,所以在看源码过程中一定不能被细枝末节缠住,一定要先理清楚整个框架的一个大致思想和大致的框架体系,再去搞那些细枝末节,其效率会好很多,其次在看源码过程中,我们一定要大胆的去想,去猜测,如果这个功能让你自己去写,你会怎么实现!

我们今天学习SpringBean的生命周期也是按照这个8字真言去学习,通过我们之前所学,Spring大致有以下的功能:

  1. 他会帮我们自动的创建对象然后保存起来!
  2. 他会帮我们完成属性的填充!
  3. 如果我们设置了Aop的功能,他会帮我们自动的代理,实现切面功能!

我们从平常的使用中,至少可以得知以上的三点,如果让你自己去实现,必会如何实现呢?

  • 首先他既然能够帮我们自己创建对象,那么他肯定是通过反射来创建的,通过反射来创建,就必定绕不过去要使用Class对象创建,那么我们如何获取Class对象呢? 去扫描项目,将指定的包下的加了注解的类文件切割获取Class名称,通过反射加载Class名称,反射创建java对象!
  • 我们要完成属性的填充,为了方便和性能方面,我肯定会把这些创建好的对象保存起来,无疑Map容器是最合适的!
  • 我们在创建一个对象完成之后,反射拿到里面的属性,如果需要填充,我们先去我们之前保存的容器里面去取,取不出来在反射吧这个依赖的属性创建出来,然后填充进对象再保存在容器里面,从而完成了属性的注入!
  • 填充完成属性之后,我们那当前对象,取与Aop逻辑进行对比,判断是否需要代理,不需要则创建完成,保存进Map容器,需要代理则对当前这个类进行jdk或者cglib的代理然后再保存进容器里面!

于是乎,我们自己实现了一个Spring管理一个Bean的所有过程,画个图,他大概长这样!

自己实现看起来,整个流程就很清晰,扫描、创建、注入、代理、保存一应俱全,但是Spring的实现方式远比我们自己实现的要复杂的多得多!

三、Spring的生命周期流程

Spring作者希望,Spring再着手管理一个Bean的时候,它希望能够让Spring的使用者能够插手,Spring把一个类对象变成一个Java Object的每一步,怎么理解呢?

比如我们买了一栋新房子,这个房子需要取装修,你自己去装修诚然不够专业,不能够面面俱到,所以是我们就找了一个装修公司帮助我们装修新房,于是装修公司就开始预先画好的图纸进行装修,但是在装修的过程中,你为了让自己的新家更加温馨,你想挂一些壁画在墙上,但是图纸上却没有!于是你就找装修公司,要求装修公司在新家的墙上挂上一些壁画!装修公司在接受到你的请求之后,就吩咐装修的工人在图纸之外去给你在墙上挂上壁画之后,然后再接着装修!

上面这个小故事有 这样几个角色,我们把它和Spring对照起来!

  • 你:代表框架的使用者!
  • 新房:代表一个Class文件,你自己也能够装修,但是不够专业,所以交给装修公司! 那么你自己创建对象可能某些使用用起来很麻烦,所以我们交给了Spring容器!
  • 装修公司:代表着Spring容器!
  • 图纸:代表预设步骤,Spring原本就存在的步骤!
  • 工人:Spring提供的各种接口!我们可以通过Spring工厂提供的接口做各种自定义的配置!

上面的小故事,大致可以描述Spring生命周期的核心思想!Spring再对一个Class文件实例化成具体的Spring Bean的时候,它提供了各种接口,由我们自己实现!然后再实例化过程中,不同的时机,去调用不同的接口!从而完成Spring的整个生命周期的创建!

Spring的生命周期大致分为以下部分!

  1. 扫描项目,将项目指定目录下的Class文件转换为Class对象!

  2. 读取Class对象属性包装为BeanDefinition,然后保存再一个Map中!(不难理解,他是为了后续创建或者读取这个类的信息更加方便取而创立的)

  3. 将全部的类转化为 BeanDefinition 并保存之后,开始调用第一个回调接口BeanFactoryPostProcessor#postProcessBeanFactory()!

    • 它的调用时机是将扫描到的Class文件转换为 BeanDefinition 之后调用的,我们可以通过回调的方法获取所有的BeanDefinition ,而后续的所有对Class的操作都是基于BeanDefinition 操作的,所以,我们可以通过修改它,来改变后续的流程!
  4. 先从当前的容器对象取当前要创建的对象,当取出来的对象为null时开始着手创建对象!

  5. 做一系列的验证,比如验证这个类是否被排除、是否正在创建中、是否有依赖Bean【@DependsOn】注解、是否时单例等等!

  6. 验证通过之后,开始通过反射创建这个对象!

  7. 合并BeanDefinition ,这里涉及到Spring之前版本使用的父子容器的概念,属于另外一个知识点不做讲解!

  8. 判断当前对象是不是单例、是不是支持循环引用、是不是正在创建等!

  9. 执行第二个接口回调InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation()方法!

    • 它的执行时机时实例化完成之后,属性填充之前,它的返回值是一个布尔值,当返回false时,不做自动属性填充!
  10. 执行第三个接口回调InstantiationAwareBeanPostProcessor#postProcessProperties()方法!

    • 他的执行时机是,实例化之后,属性填充检查之后,属性填充之前!它会返回一个属性,后续的属性填充会使用这个方法返回的值!我们可以在这个方法里面修改对应Bean的注入的值!
  11. 填充属性到对象!

  12. 调用第四个回调接口BeanNameAware#setBeanName()方法!

    • 调用时机:属性填充给完毕后,调用初始化方法之前;它的功能是能获取bean的Name!
  13. 调用第五个回调接口BeanClassLoaderAware#setBeanClassLoader()

    • 调用时机:BeanNameAware之后,他的功能是传入bean的类加载器;
  14. 调用第六个回调接口BeanFactoryAware#setBeanFactory()!

    • 调用时机:BeanClassLoaderAware之后,用于设置beanFactory!
  15. 调用第七个回调接口BeanPostProcessor#postProcessBeforeInitialization()方法

    • 调用时机是部分Aware之后,初始化方法之前!传入当前实例化好的对象和beanName,再初始化前做修改!
  16. 回调第八个比较重要的生命周期的初始化方法,它可以是一个InitializingBean接口的bean,也可以是xml中配置的类,也可以是被加了@PostConstruct注解的方法!

    • 该方法内部逻辑可以用户自己编写,调用时机为:实例化完成之后调用!
  17. 回调第九个回调接口 BeanPostProcessor#postProcessAfterInitialization()方法!

    • 该方法的调用时机为初始化方法执行之后,这里也是Bean实例化后的最后一步,也是SpringAop实现的重要的一步!
  18. 注册销毁方法,以便Spring容器销毁的时候进行方法的销毁!

整体的方法流程示例图如下:

四、对应源码结构图

最后

现在其实从大厂招聘需求可见,在招聘要求上有高并发经验优先,包括很多朋友之前都是做传统行业或者外包项目,一直在小公司,技术搞的比较简单,没有怎么搞过分布式系统,但是现在互联网公司一般都是做分布式系统。

所以说,如果你想进大厂,想脱离传统行业,这些技术知识都是你必备的,下面自己手打了一份Java并发体系思维导图,希望对你有所帮助。

资料获取方式:戳这里免费下载

业,这些技术知识都是你必备的,下面自己手打了一份Java并发体系思维导图,希望对你有所帮助。

资料获取方式:戳这里免费下载

java定时任务cron表达式相关推荐

  1. java定时任务cron表达式每周执行一次的坑

    java springboot 利用schedule执行定时任务是很常用的功能,有一个很常用的网站就是在线Cron表达式生成器,但是在这个网站最近遇到一个坑. 我要每周四执行一次,我把我写的表达式在这 ...

  2. java定时任务cron表达式 ,每周五下午两点半执行

    @Scheduled(cron = "0 30 14 ? * 5") 信了其他文章的鬼,也可能java不一样,DayofWeek这个参数 1就是周一,2就是周二,用代码验证过了.

  3. 定时任务Cron表达式学习

    有关定时任务Cron表达式的那些 背景:今天在做quartZ定时任务,发现了要用Cron表达式去指定出发的时间表. 1.CronTrigger CronTrigger,你可以指定触发的时间表如&quo ...

  4. java生成cron表达式构造器

    package org.oreframework.util.scheduling;import java.util.Calendar;/*** @Title: CronBuilder.java* @D ...

  5. Spring Boot定时任务-cron表达式

    其实cron表达式呢,其实就是一个基于字符串的,基于时间的一个定义格式,那我们就来看一下cron表达式语法的定义,cron表达式它是一个字符串的,并且在字符串当中呢,包含6个域或者7个域,然后每个域表 ...

  6. 定时任务 cron 表达式详解

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. (Spring定时任务的几种实现:见博客另一页:http://blog.csdn.net/jiang ...

  7. 定时任务cron表达式使用详解

    项目中有时会需要定时去触发一些任务,Java实现定时任务一般有三种方法: JDK自带的Timer以及JDK1.5+ 新增的ScheduledExecutorService: Quartz 定时器:简单 ...

  8. 定时任务 ||​​​​​​​​​​​​​​ Cron表达式

    Spring内置的Spring Task,这是Spring3.0加入的定时任务功能. 使用注解的方式定时启动爬虫进行数据爬取. 我们使用的是@Scheduled注解,其属性如下: 1)cron:cro ...

  9. linux定时任务 - CRON表达式

    CRON 表达式是一个字符串,以 5 或 6 个空格隔开,分为 6 或 7 个域,每一个域代表一个含义. CRON 有如下两种语法格式: 秒 分 小时 日期 月份 星期 年 秒 分 小时 日期 月份 ...

最新文章

  1. C#中生产者线程和消费者线程同步的实现
  2. Python Open Source Project List
  3. 5.数字拆分成4段,怎样使得4段的乘积最小【dp】
  4. C#读取与修改XML文档
  5. java jedis sadd_Java实现Redis的集合(set)命令操作
  6. 泛型--定制泛型接口、泛型类--介绍篇
  7. Android之用命令uninstall卸载apk和用 -i 过滤日志忽略大小写
  8. java8 默认方法_如何不使用Java 8默认方法
  9. Java面试知识点:多态、内部类
  10. 计算机初赛基础知识,备战初赛计算机基础知识
  11. django -- 分页功能
  12. Atiitt 管理方面的误区总结 attilax总结
  13. python写刷课脚本_python opencv 知到 刷课 脚本
  14. [二维压缩] | 条件图像游程编码
  15. 中国月球探测标识确定 寓龙的传人登月梦
  16. CERC2017 F-Faulty Factorial【数论】
  17. 在不同位置(客户端的终端设备,服务端,项目代码中)判断设备类型(PC、手机、微信等)
  18. 敏捷式Mybatis
  19. java微信摇一摇_微信摇一摇功能实现
  20. 苹果保修期多久_二手苹果手机怎么验机?

热门文章

  1. go-micro V2 从零开始(四)集成micro api网关
  2. Unity3D游戏编程-牧师与恶魔
  3. Sketch Mac入门基础知识——蒙版(Mask)的详细使用方法介绍
  4. Unity3D学习笔记(二十三)导入WOW角色
  5. 100 道 JavaScript 面试题及答案汇总(下)
  6. B.3【智能标注】:基于Labelstudio的UIE半监督深度学习的智能标注方案(云端版),提效。
  7. 用python股票代码_利用Python将股票代码表导入表格
  8. 通过组策略来防治U盘病毒
  9. ProcessDB实时/时序数据库——C/C++连接数据库
  10. 论文阅读笔记(3)---基于深度学习的节律异常或传导阻滞多标签心电图自动诊断