SpringBean 的实例化过程

作者: Tim在路上 | 来源:发表于2020-05-31 09:15 被阅读0次

一个Bean 的实例化过程

不通过new 对象 Spring 是如何实例化对象的?

  1. 创建一个javaBean , 并在Spring.xml 中进行配置
  2. 在使用是通过解析xml 返回 bean 工厂
  3. 通过 bean 工厂返回相应的 Bean

怎么从 BeanFactory 中拿到相应的 Bean ?

  1. 第一步获取 Bean 的真正name

因为 bean 在配置时有两种情况,1. 别名 2. 传入是工厂的Bean名,例如 &beanName

  1. 如果获取的Bean 的 scope 是 singleton 单利,在实例化bean的时候spring会将其缓存起来,从缓存中读取 bean
  2. 如果第一层创建Bean,如果是原型原型模式下是无法解决循环依赖,(a 中有 b, b 中有 a)直接抛异常;
  3. 如果 bean 中有依赖的 Bean ,递归注册
  4. 如果是单利,依赖Bean完成创建实例本身,首先创建工厂缓存bean,然后由工厂bean创建返回真实bean对象
  5. 如果是原型,直接创建bean 进行返回。

Bean 存在 正在创建的情况。

循环依赖,spring解决单例模式循环依赖问题的方法是提前曝光,意思是假设检测到了循环依赖的话

spring会将循环依赖的对象提前创建好,到使用的时候直接获取就好

注解Bean 的解析注册过程

我们使用 @Service @Component 时,需要配置一个扫描器

当在一个javaBean上标注@service时spring初始化做了什么?

  1. 创建 JavaBean 并标注 @Service标注
  2. 解析 Bean
  3. 判断节点的命名空间类别 注解 采用默认的解析类型
  4. 获取对象的命名空间,获取命名空间对应的处理器

@Autoware 解析过程

名称:bean解析是通过bean名称
类型:解析过程基于bean的类型

@Autowired应该通过@Qualifier注解协作注入。例如下面几个是相同类型的bean:

如果一个类在Spring 中配置了两个 bean

假如只是一个简单的@Autowired,Spring根本不知道你要注入哪个bean。这就是为什么我们要使用@Qualifier(value =“beanName”)这个注解

  1. 启动注解的自动注入 <context:annotation-config />
  2. 进行注入
    @Qualifier(value="comment1")
    @Autowired
    private Comment firstComment;
     
    @Qualifier(value="comment2")
    @Autowired
    private Comment secondComment;

而且我们注入的类也必须是由 Spring 所管理的

Spring容器,被称为应用程序上下文。这意味着我们不需要处理他们的生命周期(初始化,销毁)。该任务由此容器来完成。

类内部的注解,如:@Autowired、@Value、@Required、@Resource以及EJB和WebSerivce相关的注解,是容器对Bean对象实例化和依赖注入时,通过容器中注册的Bean后置处理器处理这些注解的。

  1. 当 Spring 容器启动时,AutowiredAnnotationBeanPostProcessor 将扫描 Spring 容器中所有 Bean,当发现 Bean 中拥有@Autowired 注解时就找到和其匹配(默认按类型匹配)的 Bean,并注入到对应的地方中去。
  2. AutowiredAnnotationBeanPostProcessor可以实现依赖自动注入。通过这个类来处理@Autowired和@Value这俩Spring注解。
  3. buildAutowiringMetadata 解析等待自动注入类的所有属性。它通过分析所有字段和方法并初始化

Spring IOC 的 容器的加载过程

  1. 刷新容器,标记容器启动
  2. 将配置信息解析,注册到BeanFactory
  3. 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
  4. Bean 如果实现了BeanFactoryPostProcessor 接口,那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事,用于初始化前做点什么(例如修改属性的值,修改bean的scope为单例或者多例
  5. 初始化当前的事件广播器
  6. 初始化所有的 singleton beans(lazy-init 的除外
  7. 广播applicationcontext初始化完成

cookie 保存在客户端,容易篡改
session 保存在服务端,连接较大的话会给服务端带来压力,分布式的情况下可以放在数据库中,
优点:
1:简单且高性能
2:支持分布式与集群
3:支持服务器断电和重启
4:支持 tomcat、jetty 等运行容器重启
缺点:
1、需要检查和维护session过期,手动维护cookie;
2、不能有频繁的session数据存取;

session 在服务器端,cookie 在客户端(浏览器)
2,session 默认被存在在服务器的一个文件里(不是内存)
3,session 的运行依赖 session id,而 session id 是存在 cookie 中的,也就是说,如果浏览器禁用了 cookie ,同时 session 也会失效(但是可以通过其它方式实现,比如在 url 中传递 session_id)
4,session 可以放在 文件、数据库、或内存中都可以。
5,用户验证这种场合一般会用 session

不同浏览器对cookie 的大小 和 个数 的限制不同。

Session 的大小是没有限制的。

Cookie 有两种保存形式 1. 保存在磁盘,文件除非用户手工清理或到了过期时间,硬盘Cookie不会被删除,其存在时间是长期的。 2. 保存在内存中--进程COOKIE:
由浏览器维护,首先要知道,打开浏览器时,会启用进程,该COOKIE就保存在打开浏览器的进程中,当浏览器关闭时,进程结束,COOKIE也就消失了

SESSION是通过SESSIONID来实现,而SESSIONID是保存在COOKIE中

当你第一次访问网站并向服务器发送请求时,服务器端会在响应头上添加JSESSIONID,此ID是服务器随机生成而且是唯一的,这个JSESSIONID其实就是SESSIONID.SESSIONID会先将自己保存 在COOKIE中,然后根据SESSIONID在服务器端(也就是ACTION中)是否已存在来判断是新建SESSION还是直接获取SESSION

当浏览器关闭后(在SESSION的有效期间),SESSION是不会消失的.只有人为调用SESSION.invalidate方法或者是超过了有效时间(有效时间默认的有效时间是30分钟

不管浏览器是够关闭,30分钟内如果没有进行操作,就会被视为超过了有效期)来清除.

如果SESSIONID是保存在了进程COOKIE中,那么当浏览器关闭后,COOKIE随浏览器进程一起消失,SESSIONID也就消失了,需要声明的是,此时服务器端的SESSION并不会消失(在有效时间内).当再次打开浏览器并向服务器端发送请求时,因为原来的SESSIONID已经不存在,服务器会生成一个全新的JSESSIONID,此ID在服务器端是全新的,也就是说根据此ID匹配不到相应的SESSION,所以服务器会为该SESSIONID创建一个全新的SESSION,并进行绑定

相关文章

网友评论

    本文标题:SpringBean 的实例化过程

    本文链接:https://www.haomeiwen.com/subject/avklzhtx.html