一个Bean 的实例化过程
不通过new 对象 Spring 是如何实例化对象的?
- 创建一个javaBean , 并在Spring.xml 中进行配置
- 在使用是通过解析xml 返回 bean 工厂
- 通过 bean 工厂返回相应的 Bean
怎么从 BeanFactory 中拿到相应的 Bean ?
- 第一步获取 Bean 的真正name
因为 bean 在配置时有两种情况,1. 别名 2. 传入是工厂的Bean名,例如 &beanName
- 如果获取的Bean 的 scope 是 singleton 单利,在实例化bean的时候spring会将其缓存起来,从缓存中读取 bean
- 如果第一层创建Bean,如果是原型原型模式下是无法解决循环依赖,(a 中有 b, b 中有 a)直接抛异常;
- 如果 bean 中有依赖的 Bean ,递归注册
- 如果是单利,依赖Bean完成创建实例本身,首先创建工厂缓存bean,然后由工厂bean创建返回真实bean对象
- 如果是原型,直接创建bean 进行返回。
Bean 存在 正在创建的情况。
循环依赖,spring解决单例模式循环依赖问题的方法是提前曝光,意思是假设检测到了循环依赖的话
spring会将循环依赖的对象提前创建好,到使用的时候直接获取就好
注解Bean 的解析注册过程
我们使用 @Service @Component 时,需要配置一个扫描器
当在一个javaBean上标注@service时spring初始化做了什么?
- 创建 JavaBean 并标注 @Service标注
- 解析 Bean
- 判断节点的命名空间类别 注解 采用默认的解析类型
- 获取对象的命名空间,获取命名空间对应的处理器
@Autoware 解析过程
名称:bean解析是通过bean名称
类型:解析过程基于bean的类型
@Autowired应该通过@Qualifier注解协作注入。例如下面几个是相同类型的bean:
如果一个类在Spring 中配置了两个 bean
假如只是一个简单的@Autowired,Spring根本不知道你要注入哪个bean。这就是为什么我们要使用@Qualifier(value =“beanName”)这个注解
- 启动注解的自动注入 <context:annotation-config />
- 进行注入
@Qualifier(value="comment1")
@Autowired
private Comment firstComment;
@Qualifier(value="comment2")
@Autowired
private Comment secondComment;
而且我们注入的类也必须是由 Spring 所管理的
Spring容器,被称为应用程序上下文。这意味着我们不需要处理他们的生命周期(初始化,销毁)。该任务由此容器来完成。
类内部的注解,如:@Autowired、@Value、@Required、@Resource以及EJB和WebSerivce相关的注解,是容器对Bean对象实例化和依赖注入时,通过容器中注册的Bean后置处理器处理这些注解的。
- 当 Spring 容器启动时,AutowiredAnnotationBeanPostProcessor 将扫描 Spring 容器中所有 Bean,当发现 Bean 中拥有@Autowired 注解时就找到和其匹配(默认按类型匹配)的 Bean,并注入到对应的地方中去。
- AutowiredAnnotationBeanPostProcessor可以实现依赖自动注入。通过这个类来处理@Autowired和@Value这俩Spring注解。
- buildAutowiringMetadata 解析等待自动注入类的所有属性。它通过分析所有字段和方法并初始化
Spring IOC 的 容器的加载过程
- 刷新容器,标记容器启动
- 将配置信息解析,注册到BeanFactory
- 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
- Bean 如果实现了BeanFactoryPostProcessor 接口,那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事,用于初始化前做点什么(例如修改属性的值,修改bean的scope为单例或者多例
- 初始化当前的事件广播器
- 初始化所有的 singleton beans(lazy-init 的除外
- 广播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,并进行绑定
网友评论