Spring中的三级缓存及其原因

首先看下Spring创建一个bean的基本流程:

创建该实例的原始对象 --> 进行自动装配 --> AOP代理处理 --> 完成bean的创建并加入单例池(即一级缓存)

但是当有循环依赖的时候,Spring是如何解决的呢?

主要原理是利用三级缓存机制:
在这里插入图片描述

singletonObjects: 一级缓存,也就是我们平常理解的单例池。
singletonFactories: 二级缓存,存储的是单例工厂。
earlySingletonObjects: 三级缓存,存储正在创建中的单例对象。
为什么要设立三级缓存呢?

其实当不需要实现AOP的时候,解决循环依赖不用三级缓存机制,也不用单例工厂,二级缓存就足以实现。

第一级:singletonObjects
第二级:earlySingletonObjects

不需要实现AOP时Spring解决循环依赖基本流程:

假设单例一与单例二相互依赖对方并且此时都没有加入到单例池
1 创建单例一
2 将单例一加入earlySingletonObjects缓存
3 自动装配单例二
4 判断单例二在earlySingletonObjects缓存是否存在
5 不存在则创建单例二
6 将单例二并且加入earlySingletonObjects缓存
7 自动装配单例一
8 判断单例一在earlySingletonObjects缓存是否存在
9 明显第2步已经加入earlySingletonObjects缓存
10 注入成功,单例2创建完成并加入singletonObjects单例池
11 注入成功,单例1创建完成并加入singletonObjects单例池

那为什么要设立三级缓存呢?
这是因为当我们需要使用AOP时,将会对原始对象进行代理,因此最后的对象将是代理对象而不是原始对象!

所以按照二级缓存的步骤进行创建的话将会造成一个问题:

第2步加入到二级缓存中的对象是原始对象,导致第7步自动装配到到单例2中的单例1对象是原始对象,这个对象还没有完成AOP的处理。如果此时完成单例2的创建,之后在完成进行单例1的创建时,单例1对原始对象进行AOP处理,将导致最终的单例1对象不是之前自动装配到单例2中的单例1对象。

所以Spring选择使用三级缓存来解决这个问题:singletonFactories缓存中的对象是一个单例工厂,该工厂可以将原始对象进行AOP处理。

singletonObjects: 一级缓存,也就是我们平常理解的单例池。
singletonFactories: 二级缓存,存储的是单例工厂。
earlySingletonObjects: 三级缓存,存储正在创建中的单例对象。

获取三级缓存的核心代码如下:

getSingleton方法的大概处理过程为:

1 判断singletonObjects单例池中是否存在,存在则返回
2 不存在则判断earlySingletonObjects缓存中是否存在,存在则返回
3 不存在则判断singletonFactories缓存中是否存在,不存在则返回null
4 存在则通过该存储工厂创建出最终的bean
5 将该bean加入earlySingletonObjects缓存并从singletonFactories缓存中中移除

存在三级缓存机制下处理流程如下:

假设单例1与单例2相互依赖对方并且此时都没有加入到单例池
1 创建单例一
2 创建单例一的工厂对象并且加入singletonFactories缓存
3 自动装配单例二
4 通过 getSingleton方法 判断单例二在三级缓存中是否存在
5 明显此时单例一不存在,所以创建单例二
6 创建单例二的工厂并且加入singletonFactories缓存
7 自动装配单例一
8 通过 getSingleton方法 判断单例一在三级缓存中是否存在
9 明显第2步已经加入singletonFactories缓存
10 单例二进行AOP处理
11 注入单例一成功,单例二创建完成并加入singletonObjects单例池
12 注入单例二成功,单例一创建完成并加入singletonObjects单例池

以上步骤Spring就完美解决了循环依赖的问题!

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
spring-core.jar(必须):这个jar 文件包含Spring 框架基本的核心工具类。Spring 其它组件要都要使用到这个包里的类,是其它组件的基本核心,当然你也可以在自己的应用系统使用这些工具类。 外部依赖Commons Logging, (Log4J)。 spring-beans.jar(必须):这 个jar 文件是所有应用都要用到的,它包含访问配置文件、创建和管理bean 以及进行Inversion of Control / Dependency Injection(IoC/DI)操作相关的所有类。如果应用只需基本的IoC/DI 支持,引入spring-core.jar 及spring-beans.jar 文件就可以了。 外部依赖spring-core,(CGLIB)。 spring-aop.jar(必须):这个jar 文件包含在应用使用Spring 的AOP 特性时所需的类和源码级元数据支持。使用基于AOP 的Spring特性,如声明型事务管理(Declarative Transaction Management),也要在应用里包含这个jar包。 外部依赖spring-core, (spring-beans,AOP Alliance, CGLIB,Commons Attributes)。 spring-context.jar(必须):这个jar 文件在基础IOC功能上为Spring 核心提供了大量扩展服务,此外还提供许多企业级服务的支持,有邮件服务、任务调度、JNDI定位,EJB集成、远程访问、缓存以及多种视图层框架的支持。可以找到使用Spring ApplicationContext特性时所需的全部类,JDNI 所需的全部类,instrumentation组件以及校验Validation 方面的相关类。 外部依赖spring-beans, (spring-aop)。 spring-jdbc.jar(必须) :这个jar 文件包含对Spring 对JDBC 数据访问进行封装的所有类。 外部依赖spring-beans,spring-dao。 spring-web.jar(必须) :这个jar 文件包含Web 应用开发时,用到Spring 框架时所需的核心类,包括自动载入Web Application Context 特性的类、Struts 与JSF 集成类、文件上传的支持类、Filter 类和大量工具辅助类。 外部依赖spring-context, Servlet API, (JSP API, JSTL, Commons FileUpload, COS)。 spring-webmvc.jar :这个jar 文件包含Spring MVC 框架相关的所有类。包含国际化、标签、Theme、视图展现的FreeMarker、JasperReports、Tiles、Velocity、XSLT相关类。包括框架的Servlets,Web MVC框架,控制器和视图支持。当然,如果你的应用使用了独立的MVC 框架,则无需这个JAR 文件里的任何类。 外部依赖spring-web, (spring-support,Tiles,iText,POI)。 spring-aspects.jar :提供对AspectJ的支持,以便可以方便的将面向方面的功能集成进IDE,比如Eclipse AJDT。 spring-context-support.jar:Spring context的扩展支持,用于MVC方面。 spring-expression.jar:Spring表达式语言。 spring-instrument.jar:Spring对服务器的代理接口 spring-instrument-tomcat.jar:Spring对tomcat连接池的集成 spring-jms.jar:为简化jms api的使用而做的简单封装。 外部依赖spring-beans,spring-dao,JMS API。 spring-orm.jar:整合第三方的orm实现,如hibernate,ibatis,jdo以及spring 的jpa实现 spring-oxm.jar:Spring对于object/xml映射的支持,可以让JAVA与XML之间来回切换 spring-messaging.jar: spring-test.jar:对JUNIT等测试框架的简单封装 spring-tx.jar:为JDBC、Hibernate、JDO、JPA等提供的一致的声明式和编程式事务管理。 spring-webmvc-portlet.jar:Spring MVC的增强 spring-websocket.jar:
Spring.NET是一个应用程序框架,其目的是协助开发人员创建企业级的.NET应用程序。它提供了很多方面的功能,比如依赖注入、面向方面编程(AOP)、数据访问抽象及ASP.NET扩展等等。Spring.NET以Java版的Spring框架为基础,将Spring.Java的核心概念与思想移植到了.NET平台上。 第一章 序言 第二章 简介 2.1.概述 2.2.背景 2.3.模块 2.4.许可证信息 2.5.支持 第三章 背景 3.1.控制反转 第一部分 核心技术 第四章 对象对象工厂和应用程序上下文 4.1.简介 4.2.IObjectFactory,IApplicationContext和IObjectDefinition接口介绍 4.2.1.The IObjectFactory和IApplicationContext 4.2.2.对象定义 4.2.3.对象的创建 4.2.3.1.通过构造器创建对象 4.2.3.2.通过静态工厂方法创建对象 4.2.3.3.通过实例工厂方法创建对象 4.2.4.泛型类的对象创建 4.2.4.1.通过构造器创建泛型类的对象 4.2.4.2.通过静态工厂方法创建泛型类的对象 4.2.4.3.通过实例工厂方法创建泛型类的对象 4.2.5.对象标识符(id和name) 4.2.6.Singleton和Prototype 4.3.属性,协作对象,自动装配和依赖检查 4.3.1.设置对象的属性和协作对象 4.3.2.构造器参数解析 4.3.2.1.根据参数类型匹配构造器参数 4.3.2.2.根据参数索引匹配构造器参数 4.3.2.3.根据名称匹配构造器参数 4.3.3.详细讨论对象属性和构造器参数 4.3.3.1.设置空值 4.3.3.2.设置集合值 4.3.3.3.设置泛型集合的值 4.3.3.4.设置索引器属性 4.3.3.5.内联对象定义 4.3.3.6.idref节点 4.3.3.7.引用协作对象 4.3.3.8.value和ref节点的简短格式 4.3.3.9.复合属性名 4.3.4.方法注入 4.3.4.1.查询方法注入 4.3.4.2.替换任意方法 4.3.5.引用其他对象或类型的成员 4.3.5.1.使用对象或类的属性值进行注入 4.3.5.2.使用字段值进行注入 4.3.5.3.使用方法的返回值进行注入 4.3.6.IFactoryObject接口的其它实现 4.3.6.1.Log4Net 4.3.7.使用depends-on 4.3.8.自动装配协作对象 4.3.9.检查依赖项 4.4.类型转换 4.4.1.枚举类型的转换 4.4.2.内置的类型转换器 4.4.3.自定义类型转换器 4.4.3.1.使用CustomConverterConfigurer类 4.5.自定义对象的行为 4.5.生命周期接口 4.5.1.1.IInitializingObject接口和init-method属性 4.5.1.2.IDisposable接口和destroy-method属性 4.5.2.让对象了解自己的容器 4.5.2.1.IObjectFactoryAware接口 4.5.2.2.IObjectNameAware接口 4.5.3.IFactoryObject接口 4.6.抽象与子对象定义 4.7.与IObjectFactory接口交互 4.7.1.获得IFactoryObject对象本身,而非其产品 4.8.使用IObjectPostProcessor接口自定义对象 4.9.使用IObjectFactoryPostProcessor定制对象工厂 4.9.1.PropertyPlaceholderConfigurer类 4.9.1.1.使用环境变量进行替换 4.9.2.PropertyOverrideConfigurer类 4.10.使用alias节点为对象添加别名 4.11.IApplicationContext简介 4.12.配置应用程序上下文 4.12.1.注册自定义解析器 4.12.2.创建自定义资源处理器 4.12.3.配置类型别名 4.12.4.注册类型转换器 4.13.IApplicationContext接口的扩展功能 4.13.1.上下文继承 4.13.2.使用IMessageSource接口 4.13.3.在Spring.NET内部使用资源 4.13.4.松耦合事件模型 4.13.5.IApplicationContext的事件通知 4.14.定制IApplicationContex对象的行为 4.14.1.IApplicationContextAware标识接口 4.14.2.IObjectPostProcessor接口 4.14.3.IObjectFactoryPostProcessor接口 4.14.4.PropertyPlaceholderConfigurer类 4.15.从其它文件导入对象定义 4.16.服务定位器访问 第五章. IObjectWrapper接口和类型转换 5.1.简介 5.2.使用IObjectWrapper接口管理对象 5.2.1.读、写普通及嵌套的属性 5.2.2.其它功能 5.3.类型转换 5.3.1.转换枚举类型 5.4.内置类型转换器 第六章. IResource接口 6.1.简介 6.2.IResource接口 6.3.内置的IResource实现类 6.4.IResourceLoader接口 6.5.IResourceLoaderAware接口 6.6.应用程序上下文和IResource路径 第七章. 多线程和并发操作 7.1.简介 7.2.线程本地存储 7.3.同步基础 7.3.1.ISync 7.3.2.SyncHolder 7.3.3.Latch 7.3.4.Semaphore 第八章. 对象池 8.1.简介 8.2.接口和实现 第九章. Spring.NET杂记 9.1.简介 9.2.PathMatcher 9.2.1.通用规则 9.2.2.匹配文件名 9.2.3.匹配子目录 9.2.4.大小写需要考虑,斜线可以任意 第十章. 表达式求值 10.1.简介 10.2.表达式求值 10.3.语言参考 10.3.1.文字表达式 10.3.2.属性,数组,列表,字典,索引器 10.3.2.1.定义内联的数组、列表和词典 10.3.3.方法 10.3.4.操作符 10.3.4.1.关系操作符 10.3.4.2.逻辑操作符 10.3.4.3.算术运算符 10.3.5.赋值 10.3.6.表达式列表 10.3.7.类型 10.3.8.类型注册 10.3.9.构造器 10.3.10.变量 10.3.10.1.'#this'和'#root'变量 10.3.11.三元操作符(If-Then-Else) 10.3.12.列表的投影(Projection)和选择(Selection) 10.3.13. 集合处理器和聚合器 10.3.13.1.Count聚合器 10.3.13.2.Sum聚合器 10.3.13.3.Average聚合器 10.3.13.4.Minimum聚合器 10.3.13.5.Maximum聚合器 10.3.13.6.nonNull处理器 10.3.13.7.distinct处理器 10.3.13.8.sort处理器 10.3.14.引用容器对象 10.3.15.Lambda表达式 10.3.16.空目标 10.4.本章使用的示例类型 第十一章. 验证框架 11.1.简介 11.2.用法示例 11.3.验证对象组 11.4.验证对象 11.4.1.条件验证对象 11.4.2.必需性验证对象 11.4.3.正则表达式验证对象 11.4.4.通用验证对象 11.4.5.条件型验证 11.5.验证行为 11.5.1.错误消息行为 11.5.2.通用行为 11.6.引用验证对象 11.7.在ASP.NET的使用技巧 11.7.1.显示验证错误 11.7.1.1.配置错误显示类 第十二章. 使用Spring.NET进行面向方面的编程 12.1.简介 12.1.1.AOP基本概念 12.1.2.Spring.NET AOP的功能 12.1.3.Spring.NET的AOP代理 12.2.Spring.NET的切入点 12.2.1.概念 12.2.2.切入点的操作 12.2.3.Spring.NET提供的切入点实现类 12.2.3.1.静态切入点 12.2.3.2.动态切入点 12.2.4.自定义切入点 12.3.Spring.NET的通知类型 12.3.1.通知的生命周期 12.3.2.通知类型 12.3.2.1.拦截环绕通知 12.3.2.2.前置通知 12.3.2.3.异常通知 12.3.2.4.后置通知 12.3.2.5.引入通知 12.4.Spring.NET的Advisor 12.5.使用ProxyFactoryObject创建AOP代理 12.5.1.基本原理 12.5.2.ProxyFactoryObject的属性 12.5.3.代理接口 12.5.4.代理一个类 12.6.使用ProxyFactory类以编程方式创建AOP代理 12.7.管理目标对象 12.8.使用“自动代理”功能 12.8.1.自动代理对象的定义 12.8.1.1.ObjectNameAutoProxyCreator 12.8.1.2.DefaultAdvisorAutoProxyCreator 12.8.1.3.AbstractAutoProxyCreator 12.8.2.使用特性驱动的自动代理 12.9.使用TargetSources 12.9.1.动态切换TargetSource 12.9.2.池化TargetSource 12.9.3.PrototypeTargetSource 12.10.定义新的通知类型 12.11.参考资源 第十三章.通用日志抽象层 13.1.简介 13.1.1.Logging API 13.2.实现与配置 13.2.1.控制台Logger 13.3.Log4Net 第二部分. 间层数据访问 第十四章. 事务管理 14.1.简介 14.2.动机 14.3.核心接口 14.4.用事务进行资源同步 14.4.1.高层次方法 14.4.2.低层次方法 14.5.声明式事务管理 14.5.1.理解Spring.NET声明式事务管理的实现 14.5.2.第一个例子 14.5.3.Transaction特性的设置 14.5.4.通过AutoProxyCreator使用声明式事务 14.5.5.通过TransactionProxyFactoryObject使用声明式事务 14.5.6. 通过ProxyFactoryObject使用声明式事务 14.5.7. Using Abstract object definitions 14.5.8. Declarative Transactions using ProxyFactoryObject 14.6. 编程方式的事务管理 14.6.1.使用TransactionTemplate 14.6.2.使用IPlatformTransactionManager 14.7.选择编程方式还是声明方式 第十五章. 数据访问对象 15.1.简介 15.2.统一的异常体系 15.3.为数据访问对象提供的统一抽象基类 第十六章. DbProvider 16.1.简介 16.1.1.IDbProvider和DbProviderFactory 16.1.2. XML配置 16.1.3.管理连接字符串 第十七章. 使用ADO.NET进行数据访问 17.1.简介 17.2.动机 17.3.Provider抽象 17.3.1.创建IDbProvider类型的实例 17.4.命名空间 17.5.数据访问的方式 17.6.AdoTemplate简介 17.6.1.执行回调 17.6.2.在.NET 2.0执行回调 17.6.3. .NET 1.1 17.6.4.AdoTemplate方法指南 17.7.异常翻译 17.8.参数管理 17.8.1. IDbParametersBuilder 17.8.2. IDbParameters 17.9. Mapping DBNull values 17.10. Basic data access operations 17.10.1. ExecuteNonQuery 17.10.2. ExecuteScalar 17.11. Queries and Lightweight Object Mapping 17.11.1. ResultSetExtractor 17.11.2. RowCallback 17.11.3. RowMapper 17.11.4. Query for a single object 17.11.5. Query using a CommandCreator 17.12. DataTable and DataSet 17.12.1. DataTables 17.12.2. DataSets 17.13. Deriving Stored Procedure Parameters 17.14. Database operations as Objects 17.14.1. AdoNonQuery 17.14.2. AdoQuery 17.14.3. MappingAdoQuery 17.14.4. Stored Procedure 17.14.5. DataSetOperation 18. ORM集成 18.1. 简介 第三部分. Web框架 第十九章. Web框架 19.1.简介 19.2.自动装载应用程序上下文和应用程序上下文嵌套 19.2.1. 配置 19.2.2.上下文嵌套 19.3.为ASP.NET页面进行依赖注入 19.3.1.为Web控件进行依赖注入 19.4.Master Page 19.4.1.将子页面与Master Page关联 19.5.双向数据绑定 19.5.1.数据绑定的后台实现 19.5.1.1.绑定方向 19.5.1.2.Formatters 19.5.1.3.类型转换 19.5.1.4.数据绑定事件 19.6.本地化 19.6.1.使用Localizer进行自动本地化(“推”模型) 19.6.2.使用Localizer 19.6.3.手动应用资源(“拉”模型的本地化) 19.6.4.在Web应用程序进行图像本地化 19.6.5.全局资源 19.6.6.用户语言文化管理 19.6.6.1. DefaultWebCultureResolver 19.6.6.2. RequestCultureResolver 19.6.6.3. SessionCultureResolver 19.6.6.4. CookieCultureResolver 19.6.7.更改语言文化 19.7.结果映射 19.8.客户端脚本 19.8.1.在HTML的head节点内注册客户端脚本 19.8.2.向节点添加CSS定义 19.8.3.全局目录(Well-Known Directories) 第四部分. 服务 第二十章. .NET Remoting 20.1.简介 20.2.在服务端发布SAO 20.2.1.SAO Singleton 20.2.2.SAO SingleCall 20.2.3.IIS应用程序配置 20.3.在客户端访问SAO 20.4.CAO 最佳实践 20.5.在服务端注册CAO 20.5.1.向CAO对象应用AOP通知 20.6.在客户端访问CAO 20.6.1.向客户端的CAO对象应用AOP通知 20.7. XML Schema for configuration 20.8.参考资源 第二十一章. .NET企业服务 21.1.简介 21.2.服务组件 21.3.服务端 21.4.客户端 第二十二章. Web服务 22.1.服务端 22.1.1.消除对.asmx文件的依赖 22.1.2.向web服务注入依赖项 22.1.3.将PONO发布为web服务 22.1.4.将AOP代理发布为web服务 22.1.5.客户端的问题 22.2.客户端 22.2.1.WebServiceProxyFactory 22.2.2.WebServiceClientFactory 第二十三章. Windows后台服务 23.1.备注 23.2.简介 23.3.Spring.Services.WindowsService.Process.exe应用程序 23.3.1.安装 23.3.2.配置 23.4.将应用程序上下文发布为Windows服务 23.4.1.service.config 23.4.1.1.让应用程序了解自身的位置 23.4.2.watcher.xml - 可选的配置 23.4.3.bin目录 - 可选 23.5.自定义或扩展 23.5.1. .config文件 第五部分. 与Visual Studio.NET集成 第二十四章. 与Visual Studio.NET集成 24.1.XML编辑与验证 24.2.XML Schema的版本 24.3.集成API文档 第六部分. 快速入门程序 第二十五章. IoC快速入门 25.1.简介 25.2.Movie Finder 25.2.1.开始建立MovieFinder应用程序 25.2.2.第一个对象定义 25.2.3.属性注入 25.2.4.构造器参数注入 25.2.5.总结 25.2.6.日志 25.3.应用程序上下文和IMessageSource接口 25.3.1.简介 25.4.应用程序上下文和IEventRegistry接口 25.4.1.简介 25.5.对象池示例 25.5.1.实现Spring.Pool.IPoolableObjectFactory 25.5.2.使用池对象 25.5.3.利用executor执行并行的grep 25.6.AOP 第二十六章. AOP指南 26.1.简介 26.2.基础知识 26.2.1.应用通知 26.2.2.使用切入点-基本概念 26.3.深入探讨 26.3.1.其它类型的通知 26.3.1.1.前置通知 26.3.1.2.后置通知 26.3.1.3.异常通知 26.3.1.4.引入(mixins) 26.3.1.5.通知链 26.3.1.6.配置通知 26.3.2.使用特性定义切入点 26.4.The Spring.NET AOP Cookbook 26.4.1.缓存 26.4.2.性能监视 26.4.3.重试规则 Spring.NET AOP最佳实践 第二十七章. .NET Remoting快速入门 27.1.简介 27.2.Remoting实例程序 27.3.实现 27.4.运行程序 27.5.Remoting Schema 27.6.参考资源 第二十八章. Web框架快速入门 28.1.简介 第二十九章. SpringAir - 参考程序 29.1.简介 29.2.架构 29.3.实现 29.3.1.业务层 29.3.2.服务层 29.3.3.Web层 29.4.总结 第三十章. 数据访问快速入门 30.1.简介 第三十一章. 事务管理快速入门 31.1.简介 31.2.应用程序概述 31.2.1.接口 第七部分. Java开发人员必读 第三十二章. Java开发人员必读 32.1.简介 32.2.Beans和Objects 32.3.PropertyEditor和TypeConverter 32.4.ResourceBundle和ResourceManager 32.5.异常 32.6.应用程序配置 32.7.AOP框架
Spring Security 参考 1 第一部分前言 15 1.入门 16 2.介绍 17 2.1什么是Spring Security? 17 2.2历史 19 2.3版本编号 20 2.4获得Spring安全 21 2.4.1使用Maven 21 Maven仓库 21 Spring框架 22 2.4.2 Gradle 23 Gradle存储库 23 使用Spring 4.0.x和Gradle 24 2.4.3项目模块 25 核心 - spring-security-core.jar 25 远程处理 - spring-security-remoting.jar 25 Web - spring-security-web.jar 25 配置 - spring-security-config.jar 26 LDAP - spring-security-ldap.jar 26 ACL - spring-security-acl.jar 26 CAS - spring-security-cas.jar 26 OpenID - spring-security-openid.jar 26 测试 - spring-security-test.jar 26 2.4.4检出来源 26 3. Spring Security 4.2的新特性 27 3.1 Web改进 27 3.2配置改进 28 3.3杂项 28 4.样品和指南(从这里开始) 28 5. Java配置 29 5.1 Hello Web安全Java配置 29 5.1.1 AbstractSecurityWebApplicationInitializer 31 5.1.2 AbstractSecurityWebApplicationInitializer不存在Spring 31 5.1.3使用Spring MVC的AbstractSecurityWebApplicationInitializer 32 5.2 HttpSecurity 32 5.3 Java配置和表单登录 34 5.4授权请求 35 5.5处理注销 36 5.5.1 LogoutHandler 37 5.5.2 LogoutSuccessHandler 37 5.5.3更多注销相关参考 38 5.6认证 38 5.6.1内存认证 38 5.6.2 JDBC认证 39 5.6.3 LDAP认证 39 5.6.4 AuthenticationProvider 41 5.6.5 UserDetailsService 41 5.6.6 LDAP认证 41 5.7多个HttpSecurity 41 5.8方法安全性 43 5.8.1 EnableGlobalMethodSecurity 43 5.8.2 GlobalMethodSecurityConfiguration 44 5.9后处理配置的对象 45 5.10自定义DSL 46 6.安全命名空间配置 47 6.1简介 47 6.1.1命名空间的设计 49 6.2安全命名空间配置入门 50 6.2.1 web.xml配置 50 6.2.2最小的配置 50 6.2.3表单和基本登录选项 52 设置默认的登录目的地 54 6.2.4注销处理 54 6.2.5使用其他身份验证提供程序 55 添加密码编码器 56 6.3高级Web功能 56 6.3.1记得我认证 56 6.3.2添加HTTP / HTTPS通道安全 57 6.3.3会话管理 57 检测超时 57 并发会话控制 58 会话固定攻击保护 59 6.3.4 OpenID支持 60 属性交换 61 6.3.5响应头 62 6.3.6添加你自己的过滤器 62 设置一个自定义的AuthenticationEntryPoint 64 6.4方法安全 64 6.4.1 元素 65 使用protect-pointcut添加安全性切入点 66 6.5默认AccessDecisionManager 67 6.5.1自定义AccessDecisionManager 67 6.6验证管理器和命名空间 67 7.示例应用程序 69 7.1教程示例 69 7.2联系人 69 7.3 LDAP样本 71 7.4 OpenID示例 71 7.5 CAS样品 71 7.6 JAAS样品 72 7.7预认证样本 72 8. Spring Security社区 72 8.1问题跟踪 72 8.2成为参与 73 8.3更多信息 73 第二部分 架构与实现 73 9.技术概述 73 9.1运行环境 73 9.2核心组件 74 9.2.1 SecurityContextHolder,SecurityContext和认证对象 74 获取有关当前用户的信息 75 9.2.2 UserDetailsService 75 9.2.3授予权力 77 9.2.4总结 77 9.3认证 78 9.3.1什么是Spring Security的认证? 78 9.3.2直接设置SecurityContextHolder内容 80 9.4 Web应用程序的身份验证 81 9.4.1 ExceptionTranslationFilter 82 9.4.2 AuthenticationEntryPoint 82 9.4.3认证机制 82 9.4.4在请求之间存储SecurityContext 83 9.5 Spring Security的访问控制(授权) 84 9.5.1安全和AOP建议 84 9.5.2安全对象和AbstractSecurityInterceptor 85 什么是配置属性? 85 RunAsManager 86 AfterInvocationManager 86 扩展安全对象模型 87 9.6本地化 87 10.核心服务 89 10.1 AuthenticationManager,ProviderManager和AuthenticationProvider 89 10.1.1成功认证时清除证书 91 10.1.2 DaoAuthenticationProvider 91 10.2 UserDetailsService实现 92 10.2.1内存认证 92 10.2.2 JdbcDaoImpl 93 权威组织 94 10.3密码编码 94 10.3.1什么是散列? 95 10.3.2添加盐到哈希 95 10.3.3散列和认证 96 10.4Jackson 支持 96 第三部分 测试 97 11.测试方法安全性 97 11.1安全测试设置 98 11.2 @WithMockUser 98 11.3 @WithAnonymousUser 100 11.4 @用户详细信息 101 11.5 @WithSecurityContext 102 11.6测试元注释 104 12. Spring MVC测试集成 104 12.1设置MockMvc和Spring Security 104 12.2 SecurityMockMvcRequestPostProcessors 105 12.2.1使用CSRF保护进行测试 105 12.2.2在Spring MVC测试以用户身份运行测试 106 12.2.3使用RequestPostProcessor在Spring MVC测试以用户身份运行 106 作为用户在Spring MVC测试使用注释运行 108 12.2.4测试HTTP基本认证 109 12.3 SecurityMockMvcRequestBuilders 109 12.3.1测试基于表单的认证 109 12.3.2测试注销 110 12.4 SecurityMockMvcResultMatchers 110 12.4.1未经认证的声明 111 12.4.2认证断言 111 第四部分 Web应用程序安全 112 13.安全过滤器链 112 13.1 DelegatingFilterProxy 112 13.2 FilterChainProxy 113 13.2.1绕过滤网链 115 13.3过滤器排序 115 13.4请求匹配和HttpFirewall 116 13.5与其他基于过滤器的框架一起使用 118 13.6高级命名空间配置 118 14.核心安全筛选器 119 14.1 FilterSecurityInterceptor 119 14.2 ExceptionTranslationFilter 121 14.2.1 AuthenticationEntryPoint 122 14.2.2 AccessDeniedHandler 122 14.2.3 SavedRequest和RequestCache接口 123 14.3 SecurityContextPersistenceFilter 123 14.3.1 SecurityContextRepository 124 14.4 UsernamePasswordAuthenticationFilter 125 14.4.1认证成功与失败的应用流程 125 15. Servlet API集成 127 15.1 Servlet 2.5+集成 127 15.1.1 HttpServletRequest.getRemoteUser() 127 15.1.2 HttpServletRequest.getUserPrincipal() 127 15.1.3 HttpServletRequest.isUserInRole(String) 128 15.2 Servlet 3+集成 128 15.2.1 HttpServletRequest.authenticate(HttpServletResponse) 128 15.2.2 HttpServletRequest.login(String,String) 129 15.2.3 HttpServletRequest.logout() 129 15.2.4 AsyncContext.start(Runnable) 129 15.2.5异步Servlet支持 130 15.3 Servlet 3.1+集成 131 15.3.1 HttpServletRequest#changeSessionId() 132 16.基本和摘要式身份验证 132 16.1 BasicAuthenticationFilter 132 16.1.1配置 132 16.2 DigestAuthenticationFilter 133 16.2.1配置 135 17.记住我的身份验证 136 17.1概述 136 17.2简单的基于哈希的令牌方法 136 17.3持久性令牌方法 137 17.4记住我的接口和实现 138 17.4.1 TokenBasedRememberMeServices 138 17.4.2 PersistentTokenBasedRememberMeServices 139 18.跨站点请求伪造(CSRF) 140 18.1 CSRF攻击 140 18.2同步器令牌模式 141 18.3何时使用CSRF保护 142 18.3.1 CSRF保护和JSON 142 18.3.2 CSRF和无状态浏览器应用程序 143 18.4使用Spring Security CSRF保护 143 18.4.1使用适当的HTTP动词 144 18.4.2配置CSRF保护 144 18.4.3包含CSRF令牌 145 表单提交 145 Ajax和JSON请求 145 CookieCsrfTokenRepository 146 18.5 CSRF警告 147 18.5.1超时 148 18.5.2登录 148 18.5.3注销 149 18.5.4多部分(文件上传) 149 在Spring Security之前放置MultipartFilter 150 包含CSRF令牌 151 18.5.5隐藏的HttpMethodFilter 151 18.6覆盖默认值 151 19. CORS 152 20.安全性HTTP响应头 154 20.1默认的安全头 154 20.1.1缓存控制 157 20.1.2内容类型选项 158 20.1.3 HTTP严格传输安全(HSTS) 159 20.1.4 HTTP公钥密码(HPKP) 161 20.1.5 X-Frame-Options 163 20.1.6 X-XSS保护 164 20.1.7内容安全策略(CSP) 165 配置内容安全策略 166 其他资源 168 20.1.8推荐人政策 168 配置引用者策略 169 20.2自定义标题 169 20.2.1静态头 169 20.2.2标题作者 170 20.2.3 DelegatingRequestMatcherHeaderWriter 171 21.会议管理 172 21.1 SessionManagementFilter 173 21.2 SessionAuthenticationStrategy 173 21.3并发控制 174 21.3.1查询当前通过身份验证的用户及其会话的SessionRegistry 176 22.匿名身份验证 177 22.1概述 177 22.2配置 178 22.3 AuthenticationTrustResolver 179 23. WebSocket安全 180 23.1 WebSocket配置 181 23.2 WebSocket身份验证 182 23.3 WebSocket授权 182 23.3.1 WebSocket授权说明 183 消息类型的WebSocket授权 184 目的地上的WebSocket授权 184 23.3.2出站消息 185 23.4执行相同的来源政策 185 23.4.1为什么同源? 185 23.4.2 Spring WebSocket允许的来源 186 23.4.3添加CSRF到Stomp头 186 23.4.4在WebSockets禁用CSRF 187 23.5使用SockJS 187 23.5.1 SockJS和框架选项 187 23.5.2轻松放松CSRF 188 第五部分授权 190 24.授权体系结构 190 24.1当局 190 24.2预调用处理 191 24.2.1 AccessDecisionManager 191 24.2.2基于投票的AccessDecisionManager实现 192 RoleVoter 193 AuthenticatedVoter 194 自定义选民 194 24.3调用处理后 194 24.4分层角色 196 25.安全的对象实现 197 25.1 AOP联盟(MethodInvocation)安全拦截器 197 25.1.1显式MethodSecurityInterceptor配置 197 25.2 AspectJ(JoinPoint)安全拦截器 198 26.基于表达式的访问控制 200 26.1概述 200 26.1.1通用内置表达式 201 26.2网络安全表达式 202 26.2.1在Web安全表达式引用Bean 203 26.2.2 Web安全表达式的路径变量 204 26.3方法安全表达式 204 26.3.1 @Pre和@Post注释 205 访问控制使用@PreAuthorize和@PostAuthorize 205 使用@PreFilter和@PostFilter进行过滤 207 26.3.2内置表达式 207 PermissionEvaluator接口 208 方法安全元注释 209 第六部分 其他主题 209 27.域对象安全(ACL) 209 27.1概述 209 27.2重要概念 211 27.3入门 214 28.预认证方案 216 28.1预认证框架类 216 28.1.1 AbstractPreAuthenticatedProcessingFilter 217 J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource 217 28.1.2 PreAuthenticatedAuthenticationProvider 218 28.1.3 Http403ForbiddenEntryPoint 218 28.2具体实施 219 28.2.1请求头认证(Siteminder) 219 Siteminder示例配置 219 28.2.2 Java EE容器认证 220 29. LDAP认证 220 29.1概述 220 29.2在Spring Security使用LDAP 221 29.3配置LDAP服务器 221 29.3.1使用嵌入式测试服务器 222 29.3.2使用绑定认证 222 29.3.3加载权限 223 29.4实现类 223 29.4.1 LdapAuthenticator实现 224 通用功能 224 认证者 225 PasswordComparisonAuthenticator 225 29.4.2连接到LDAP服务器 225 29.4.3 LDAP搜索对象 225 FilterBasedLdapUserSearch 225 29.4.4 LdapAuthoritiesPopulator 226 29.4.5 Spring Bean配置 226 29.4.6 LDAP属性和定制的UserDetails 227 29.5 Active Directory认证 228 29.5.1 ActiveDirectoryLdapAuthenticationProvider 228 活动目录错误代码 229 30. JSP标签库 230 30.1声明Taglib 230 30.2授权标签 230 30.2.1禁用测试的标签授权 231 30.3认证标签 232 30.4 accesscontrollist标签 232 30.5 csrfInput标签 233 30.6 csrfMetaTags标签 233 31 Java认证和授权服务(JAAS)提供者 235 31.1概述 235 31.2摘要:Java认证提供者 235 31.2.1 JAAS CallbackHandler 235 31.2.2 JAAS权威机构 236 31.3 DefaultJaasAuthenticationProvider 237 31.3.1 InMemoryConfiguration 237 31.3.2 DefaultJaasAuthenticationProvider示例配置 238 31.4 JaasAuthenticationProvider 239 31.5作为主题运行 240 32. CAS认证 240 32.1概述 240 32.2 CAS的工作原理 240 32.2.1 Spring安全和CAS交互序列 241 32.3 CAS客户端的配置 244 32.3.1服务票据认证 244 32.3.2单一注销 246 32.3.3使用CAS认证无状态服务 249 配置CAS以获取代理授予票证 249 使用代理票证调用无状态服务 250 32.3.4代理票证认证 251 33. X.509认证 253 33.1概述 253 33.2将X.509身份验证添加到您的Web应用程序 253 33.3在Tomcat设置SSL 254 34.运行认证替换 255 34.1概述 255 34.2配置 255 35. Spring Security加密模块 257 35.1简介 257 35.2加密器 257 35.2.1 BytesEncryptor 257 35.2.2 TextEncryptor 258 35.3关键发电机 258 35.3.1 BytesKeyGenerator 258 35.3.2 StringKeyGenerator 259 35.4密码编码 259 36.并发支持 260 36.1 DelegatingSecurityContextRunnable 260 36.2 DelegatingSecurityContextExecutor 262 36.3 Spring安全性并发类 264 37. Spring MVC集成 265 37.1 @EnableWebMvcSecurity 265 37.2 MvcRequestMatcher 265 37.3 @AuthenticationPrincipal 268 37.4 Spring MVC异步集成 271 37.5 Spring MVC和CSRF集成 271 37.5.1自动令牌包含 271 37.5.2解析CsrfToken 272 第七部分 Spring数据集成 273 38. Spring Data&Spring安全配置 273 39. @Query的安全表达式 273 第八部分 附录 274 40.安全数据库模式 274 40.1用户模式 274 40.1.1集团当局 274 40.2持久登录(记得我)架构 275 40.3 ACL模式 275 40.3.1 HyperSQL 276 40.3.2 PostgreSQL 277 40.3.3 MySQL和MariaDB 278 40.3.4 Microsoft SQL Server 279 40.3.5 Oracle数据库 280 41.安全命名空间 282 41.1 Web应用程序安全性 282 41.1.1 282 41.1.2 282 属性 283 的子元素 285 41.1.3 286 的父元素 286 属性 286 41.1.4 286 属性 287 父元素 287 41.1.5 <headers> 287 <headers>属性 288 <headers>的父元素 288 <headers>的子元素 288 41.1.6 289 属性 289 的父元素 289 41.1.7 289 属性 289 的父元素 290 41.1.8 290 属性 290 的父元素 290 41.1.9 290 的子元素 290 41.1.10 291 属性 291 的父元素 291 41.1.11 291 属性 291 的父元素 291 41.1.12 291 属性 292 的父元素 292 41.1.13 <frame-options> 292 <frame-options>属性 292 <frame-options>的父元素 293 41.1.14 [removed] 293 [removed]属性 293 [removed]的父元素 294 41.1.15 294 属性 294 的父元素 294 41.1.16 <header> 294 <header-attributes>属性 294 <header>的父元素 295 41.1.17 295 的父元素 295 属性 295 41.1.18 295 父元素 296 属性 296 41.1.19 296 的父元素 296 属性 296 41.1.20 <expression-handler> 297 <expression-handler>的父元素 297 属性 297 41.1.21 <form-login> 297 <form-login>的父元素 298 <form-login>属性 298 41.1.22 299 的父元素 300 属性 300 41.1.23 元素 300 属性 300 41.1.24 300 的父元素 300 属性 301 41.1.25 302 的父元素 302 属性 302 41.1.26 302 父元素 302 属性 303 41.1.27 303 的父元素 303 属性 303 的子元素 305 41.1.28 305 的父元素 305 属性 305 的子元素 305 41.1.29 306 的父元素 306 属性 306 41.1.30 306 的父元素 306 的子元素 307 41.1.31 307 的父元素 307 属性 307 41.1.32 307 的父元素 307 属性 307 41.1.33 元素 309 的父元素 309 属性 309 41.1.34 309 的父元素 309 属性 309 的子元素 310 41.1.35 311 的父元素 311 属性 311 41.1.36 312 的父元素 312 属性 312 41.1.37 313 属性 313 的子元素 313 41.1.38 313 的父元素 313 属性 313 41.1.39 314 属性 314 的子元素 314 41.2 WebSocket安全 314 41.2.1 315 属性 315 的子元素 316 41.2.2 316 的父元素 316 属性 316 41.3认证服务 317 41.3.1 317 属性 317 的子元素 317 41.3.2 318 的父元素 318 属性 318 的子元素 318 41.3.3 319 属性 319 41.3.4 320 的父元素 320 属性 320 的子元素 320 41.3.5 320 的父元素 321 属性 321 41.3.6 321 属性 321 的子元素 321 41.3.7 321 的父元素 322 属性 322 41.4方法安全 322 41.4.1 322 属性 322 的子元素 324 41.4.2 324 的父元素 324 属性 324 41.4.3 324 的父元素 325 325 41.4.4 325 的父元素 325 属性 325 41.4.5 325 的父元素 325 属性 325 41.4.6 326 的父元素 326 属性 326 41.4.7使用安全方法 326 父节点 326 属性 326 41.4.8 326 属性 327 的子元素 327 41.4.9 327 属性 327 的子元素 327 41.4.10 327 父元素 328 属性 328 41.5 LDAP名称空间选项 328 41.5.1使用。定义LDAP服务器 328 属性 329 41.5.2 329 的父元素 329 属性 329 的子元素 331 41.5.3 331 的父元素 331 属性 332 的子元素 332 41.5.4 332 属性 332 42.春季安全依赖 333 42.1 spring-security-core 334 42.2 spring-security-remoting 334 42.3 spring-security-web 335 42.4 spring-security-ldap 335 42.5 spring-security-config 336 42.6 spring-security-acl 336 42.7 spring-security-cas 337 42.8 spring-security-openid 337 42.9 spring-security-taglibs 338 43.代理服务器配置 338 44. Spring Security FAQ 339 44.1一般问题 339 44.1.1 Spring Security是否会处理我所有的应用程序安全要求? 339 44.1.2为什么不使用web.xml安全? 339 44.1.3需要哪些Java和Spring Framework版本? 341 44.1.4我是Spring Security的新手,我需要构建一个支持通过HTTPS进行CAS单点登录的应用程序,同时允许对某些URL进行本地基本身份验证,并对多个后端用户信息源(LDAP和JDBC)进行身份验证。我已经复制了一些我发现的配置文件,但不起作用。什么可能是错的? 341 44.2常见问题 342 44.2.1当我尝试登录时,我收到一条错误消息,指出“Bad Credentials”。怎么了? 343 44.2.2当我尝试登录时,我的应用程序进入“无限循环”,发生了什么事? 344 44.2.3我收到一条异常消息“访问被拒绝(用户是匿名的)”。怎么了? 344 44.2.4即使在我退出应用程序之后,为什么还能看到安全的页面? 345 44.2.5我得到一个异常,消息“在SecurityContext没有找到认证对象”。怎么了? 345 44.2.6我无法使LDAP认证正常工作。我的配置有什么问题? 345 44.2.7会话管理 346 44.2.8我使用Spring Security的并发会话控制来防止用户一次登录多次。登录后打开另一个浏览器窗口时,不会阻止我再次登录。为什么我可以多次登录? 347 44.2.9为什么在通过Spring Security进行身份验证时会话ID发生了变化? 347 44.2.10我正在使用Tomcat(或其他一些servlet容器),并为我的登录页面启用了HTTPS,之后切换回HTTP。这是行不通的 - 我只是在认证之后回到登录页面。 347 44.2.11我没有在HTTP和HTTPS之间切换,但是我的会话仍然丢失 348 44.2.12我试图使用并发会话控制支持,但是不会让我重新登录,即使我确定我已经注销并且没有超出允许的会话。 348 44.2.13 Spring Security正在创建一个会话,即使我已经配置了它,通过设置create-session属性为永远不会。 348 44.2.14执行POST时,我得到了一个403 Forbidden 349 44.2.15我正在使用RequestDispatcher将请求转发到另一个URL,但是我的安全限制没有被应用。 349 44.2.16我已经将Spring Security的元素添加到我的应用程序上下文,但是如果将安全注释添加到我的Spring MVC控制器bean(Struts操作等),那么它们似乎没有效果。 349 44.2.17我有一个肯定被认证的用户,但是当我在一些请求期间尝试访问SecurityContextHolder时,认证是空的。为什么我看不到用户信息? 350 44.2.18在使用URL属性时,授权JSP标记不尊重我的方法安全注释。 350 44.3 Spring安全体系结构问题 350 44.3.1我如何知道X是哪个包? 350 44.3.2名称空间元素如何映射到传统的bean配置? 351 44.3.3“ROLE_”是什么意思,为什么我的角色名字需要它? 351 44.3.4如何知道添加到我的应用程序的哪些依赖关系与Spring Security一起使用? 352 44.3.5运行嵌入式ApacheDS LDAP服务器需要哪些依赖关系? 352 44.3.6什么是UserDetailsService,我需要一个吗? 353 44.4共同的“Howto”请求 353 44.4.1我需要登录更多的信息,而不仅仅是用户名。如何添加对额外登录字段(例如公司名称)的支持? 354 44.4.2如果只有所请求的URL的片段值不同(例如/ foo#bar和/ foo#blah),我该如何应用不同的拦截url链接? 354 44.4.3如何在UserDetailsService访问用户的IP地址(或其他Web请求数据)? 354 44.4.4如何从UserDetailsService访问HttpSession? 355 44.4.5如何在UserDetailsService访问用户的密码? 355 44.4.6如何动态定义应用程序的安全URL? 355 44.4.7如何针对LDAP进行身份验证,但从数据库加载用户角色? 357 44.4.8我想修改由命名空间创建的bean的属性,但是模式没有任何东西支持它。我可以做什么放弃命名空间的使用? 358 45.从3.x迁移到4.x 359
面试高级开发的期间整理的面试题目,记录我面试遇到过的spring题目以及答案 目录 spring ThreadLocal的底层对象; 为什么@Service和@Repository放到实现类上面而不是接口类上面; spring 三种注入(就是从spring容器将bean放入对象属性值Spring下描述依赖关系@Resource, @Autowired和@Inject的区别与联系 SpringBeanFactory和ApplicationContext的区别 谈谈Spring IOC的理解,原理与实现? bean的生命周期,详细看上面 SpringBoot自动装配的过程的原理: spring的缓存; spring是如何解决的循环依赖; BeanFactory和FactoryBean有什么区别; Spring用到的设计模式; SPI 机制(Java SPI 实际上是“基于接口的编程+策略模式+配置文件”组合实现的动态加载机制), 很多地方有用到: AOP Spring的AOP的底层实现原理; 为什么jdk动态代理是必须是接口 两种动态代理的区别 AOP实现方式:aop注解或者xml配置;后来工具jar包aspects; aop的属性 事务 事务编码方式: 事务注意事项; 为什么同一个类A调用b方法事务,A方法一定要有事务(编码式的不用) @transaction多个数据源事务怎么指定数据源 传播特性有几种?7种; 某一个事务嵌套另一个事务的时候怎么办? REQUIRED_NEW和REQUIRED区别 Spring的事务是如何回滚的,实现原理; 抽象类和接口的区别,什么时候用抽象类什么时候用接口; StringBuilder和StringBuffer的区别 java值传递和引用传递
Spring框架,Bean的缓存是通过三级缓存实现的。其级缓存就是指单例Bean的缓存。 当我们首次通过Spring容器获取一个单例Bean时,Spring会先从一级缓存查找是否已经存在该Bean的实例。如果存在,则直接返回该实例;如果不存在,则继续执行后续步骤。 在后续的步骤Spring会尝试从二级缓存获取Bean的实例。二级缓存是一个用于存储原始的Bean定义信息的缓存,它是为了解决循环依赖问题而存在的。如果二级缓存存在Bean的定义信息,则Spring会根据这些信息创建一个新的Bean实例,并放入一级缓存,然后返回该实例。 如果二级缓存不存在Bean的定义信息,或者在创建Bean实例时出现了循环依赖问题,那么Spring会继续执行后续步骤。 在后续步骤Spring会尝试从三级缓存获取Bean的实例。三级缓存是一个用于存储已经创建但是尚未初始化完成的Bean实例的缓存。如果三级缓存存在Bean的实例,则Spring会使用这个实例,并将其放入一级缓存,然后返回该实例。 如果三级缓存不存在Bean的实例,或者在初始化Bean实例时出现了异常,那么Spring会继续执行后续步骤。 在后续步骤Spring会根据Bean的定义信息创建一个新的实例,并将其放入一级缓存,然后返回该实例。 总结一下,一级缓存就是用于缓存单例Bean实例的,它是SpringBean缓存机制的第一层。一级缓存的存在可以提高Bean的获取效率,避免重复创建实例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值