导图社区 Spring全家桶
这是一篇关于Spring全家桶的思维导图,主要内容有Spring Security、springAOP、springloc、springMVC、spring事务管理。
编辑于2022-08-06 14:04:04 江苏省Spring全家桶
Spring Security
简介
1.是Spring Resource社区的一个安全组件,为javaEE企业级开发提供全面安全防护。
2.可以在Controller,Service,DAO层等以加注解的方式保护应用的安全。
3.提供了细粒度权限控制,可以精细到每一个API接口,每一个业务方法,或者每一个DAO。
4.对环境无依赖,低代码耦合性,可自由组合实现特定安全功能,具有较高可定制性。
5.安全方面的领域,1.主体认证,2.授权主体。
6.在微服务架构,另一个优秀安全框架Apache Shiro无能为力。
功能
1.用户身份认证,用户登录验证。
2.用户权限(Role)认证,能否访问某一类,某一个URL。
3.API方法级别上的保护。
4.从内存中获取用户认证信息。
5.从数据库中获取用户认证信息。
Spring Security API
WebSecurityConfigurerAdapter
配置集成的类。
@EnableWebSecurity
功能
开启WebSecurity功能
方法
AuthenticationManagerBuilder
1.认证应用每一个请求
2.自动生成登录表单
3.user,password进行认证
4.用户可注销
5.阻止CSRF攻击
6.Session Fixation保护
HttpSecurity
配置请求认证规则,URL访问权限。
@EnableGlobalMethodSecurity
功能
开启方法级别上的保护
参数
prePostEnabled = true
功能
Pre和Post注解是否可用。
注解
@PreAuthorize("hasAnyAuthority('ROLE_ADMIN')") 进入方法前进行权限认证。
@PostAuthorize("hasAnyAuthority('ROLE_ADMIN')") 执行方法后进行权限认证。
secureEnable
@Secured注解是否可用。
jsr250Enabled
JSR-250注解是否可用。
springAOP
简介
AOP概念
OOP关注业务逻辑处理,代码逻辑自上而下,在这些自上而下的过程中会产生一些横切性问题,这些横切性问题和我们业务逻辑关系不大,会散落在代码各个地方,造成难以维护,AOP思想就是把业务逻辑和横切性问题进行分离,从而达到解耦的目的,提高代码的重用性和开发效率。
场景
日志记录,事务管理,效率检查,权限认证,线程池管理
SpringAOP和AspectJ
关系
SpringAOP使用了AspectJ的语法。
两种编程风格
@AspectJ support(@Aspectj注解)
Schema-based AOP support(xml)
特点
AOP是基于动态代理的,是方法级别的。
AOP可以分离业务代理和关注点代码(重复代码),再之星业务时,动态的注入关注点代码。
底层代理
方式
静态代理
继承
代理对象继承目标对象
聚合(接口)
代理对象和目标对象实现同一个接口
动态代理
类型
静态代理
聚合
简介
程序在运行前就已经存在代理类的字节码文件,代理类和原始类在运行前就已经确定。
特点
1.目标对象必须实现接口
2.代理对象要实现与目标对象一样的接口
3.代理对象里面包含了目标对象。
继承
简介
代理对象继承目标对象。
特点
和聚合一样,会产生类爆炸。
动态代理
简介
动态代理的源码在程序运行期间,通过JVM反射机制动态生成。代理类和委托类的关系是运行时在确定的。
AOP底层
JDK动态代理
特点
JDK动态代理会生成一个类去实现接口。
前提
有接口,@EnableAspectJAutoProxy(proxyTargetClass =false)默认
JDK动态代理的前提是目标类必须有实现的接口,如果某个类没有实现接口,就不能使用JDK动态代理。
CGLIB代理
特点
CGLIB是以动态生成的子类继承目标的方式实现,在运行期动态在内存中构建一个子类。
前提
没接口,@EnableAspectJAutoProxy(proxyTargetClass =false)默认
@EnableAspectJAutoProxy(proxyTargetClass =true)强制使用CGLIB,不管有没有接口
CGLIB使用的前提是目标类不能为final修饰,final的类不能被继承。
ps
编译时期织如还是运行时期织入(两者都是在运行时期织入)
初始化时期织入还是获取对象时织入(初始化时期织入)
术语
Aspect(切面)
通知,连接点,切点的集合,比如数据库事务,直接贯穿了整个代码的层面,能在被代理对象的方法之前,之后,产生异常后切入代码甚至代替原来的被代理对象,就是一个切面。
Advice(通知)
关联连接点,将代理逻辑织入到目标方法的位置。首先,Advice 通过 PointCut 查询需要被织入的 JoinPoint 。然后,Advice 在查询到 JoinPoint 上执行逻辑。
类型
Before(前置通知)
动态代理反射原有对象方法或者执行环绕通知前执行的通知功能。
After(后置通知)
动态代理反射原有对象方法或者执行环绕通知后执行的通知功能。无论是否异常,都会被执行。
After Returning(返回通知)
动态代理反射原有对象方法或者执行环绕通知后执行的通知功能。
After throwing(异常通知)
动态代理反射原有对象方法或者执行环绕通知产生异常后执行的通知功能。
Around Throwing(环绕通知)
动态代理中,覆盖原有方法,允许通过反射调用原有方法。
After(finally)
Around advice
Join point(连接点)
将要切入的目标对象的一个方法。
pointcut(切点)
切点表示连接点的集合,条件满足被扫描到的所有目标方法,如果说切点是一张表,连接点就是这张表中的一个字段。而 PointCut 的作用,就是提供一组规则来匹配 JoinPoint
weaving(织入)
把代理逻辑加入到目标对象上的过程,是一个生成代理对象的过程。
Target(目标对象)
要执行的方法,将要切入的对象。也就是织入 Advice 的目标对象。目标对象也被称为 Advised Object 。
AOP proxy(代理对象)
由于产生切面,业务逻辑增强,目标对象发生了逻辑上的改变
切点表达式
表达式
execution
简介
能定义到方法的返回类型,权限修饰符。
语法
execution(* *com.javahly.spring17.dao.IndexDao.query(..))
within
简介
最小粒度是类,不能使用在接口上。
语法
within(com.xyz.service.*)
this
简介
当前产生的代理对象的类型为该类型才切入。
语法
this(com.javahly.spring17.impl.IndexDaoImpl)
target
简介
目标对象的类型为该类型才切入。
语法
target(com.javahly.spring17.impl.IndexDaoImpl)
args
简介
根据传入的参数类型匹配,与方法名和包名无关。
语法
args(java.io.Serializable)
@annotation
简介
切入加了该注解的方法,只能用在类上,不能用在接口上,作用在方法级别。
语法
@annotation(com.javahly.spring17.annotation.Hly)
@within
简介
切入加了该注解的类。
语法
@within(com.javahly.spring17.annotation.Hly)
@target
简介
切入加了该注解的目标对象。
语法
@target(org.springframework.transaction.annotation.Transactional)
@args
简介
切入加了该注解的参数。
语法
@args(com.xyz.security.Classified)
bean
简介
切入名称为该名称的bean的所有方法。
语法
bean(dao1)
资料
文档
https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#aop
springIOC
简介
Spring容器
概念
Spring各种组件组合在一起的环境
类型
高级容器 ApplicationContext ;
低级容器 BeanFactory ;
IOC
概念
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。IOC是编程中需要达到的一种目标,DI,DL是实现IOC的一种技术手段。
实现方式
1.应用程序中提供类以及类的依赖关系。
2.把需要交给容器管理的对象通过配置信心告诉容器。
3.把各个类之间的依赖关系通过配置信息告诉容器。
依赖注入
概念
我们不需要自己创建对象,只需要描述如何创建他们。容器负责创建对象,并将他们装配在一起,配置并管理他们完整的生命周期。
方式
接口注入
Setter注入
构造方法注入
Spring自动装配
概念
IOC的注入有两个地方需要提供依赖关系,一是类的定义中,二是在spring的配置中需要去描述。自动装配则把第二个取消了,即我们仅仅需要在类中提供依赖,继而把对象交给容器管理即可完成注入。 在实际开发中,描述类之间的依赖关系通常是大篇幅的,如果使用自动装配则省去了很多配置,并且如果对象的依赖发生更新我们可以不需要去更新配置,但是也带来了一定的缺点,比如无法对原始类装配。
方式
default-autowire="default"//不使用自动装配,使用手动装配
default-autowire="byType"//根据类型装配,只能有一个实现类,不然报错
default-autowire="byName" //和SetXX的XX名有关,根据XX装配
default-autowire="constructor"
根据构造函数的参数类型来注入依赖项,若不行,通过byType。
Spring编程风格
schemal-based-------xml
annotation-based-----annotation
java-based----java Configuration
常用注解
@Autowired
默认采用ByType,ByType没有找到根据ByName,没有找到报错。
@Resource
默认采用ByName,也可以指定type和name。
@Component
@Service,@Controller等的父类,目前没有任何区别。
@Scope
类型
single 单例,prototype 原型,request,session,application,websocket
PS
single bean 引用用prototype类型的bean会失去作用
single bean只会初始化一次,多个方法无法提供不同的prototype类型的bean
解决方法:1.实现ApplicationContextAware 2.@Lockup
@Qualifier
当创建多个相同类型的 Bean ,Spring无法区别应当使用哪一个Bean,则可以使用 @Qualifier 注解和 @Autowired 通过指定ID告诉Spring应该装配哪个Bean以致消除歧义。
@Lazy
默认情况下,容器启动之后会将所有作用域为单例的 Bean 都创建好,但是有的业务场景我们并不需要它提前都创建好。设置为懒加载,当容器启动之后,作用域为单例的 Bean ,就不在创建。是在获得该 Bean 时,才真正在创建加载。
资料
https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html
http://www.mybatis.org/spring/
springMVC
简介
SpringMVC的优点
1.使用方便,无论是添加HTTP请求方法,还是以不同数据响应。
2.提供拦截器机制,可以方便的对请求进行拦截处理。
3.提供异常机制,可以方便的对异常做统一处理。
4.可以使用各种视图技术。
概念
WebApplicationContext
WebApplicationContext 是实现ApplicationContext接口的子类,专门为 WEB 应用准备的。它允许从相对于 Web 根目录的路径中加载配置文件,完成初始化 Spring MVC 组件的工作。从 WebApplicationContext 中,可以获取 ServletContext 引用,整个 Web 应用上下文对象将作为属性放置在 ServletContext 中,以便 Web 应用环境可以访问 Spring 上下文。
SpringMVC的重定向与转发
结果转发:在返回值的前面加 "forward:/" 。
重定向:在返回值的前面加上 "redirect:/" 。
Spring MVC 拦截器
#preHandle(...) 方法,调用 Controller 方法之前执行。
#postHandle(...) 方法,调用 Controller 方法之后执行。
#afterCompletion(...) 方法,处理完 Controller 方法返回结果之后执行。
Spring MVC 的拦截器和 Filter 过滤器
功能相同:拦截器和 Filter都能实现相应的功能,谁也不比谁强。
容器不同:拦截器构建在 Spring MVC 体系中;Filter 构建在 Servlet 容器之上。
使用便利性不同:拦截器提供了三个方法,分别在不同的时机执行;过滤器仅提供一个方法,当然也能实现拦截器的执行时机的效果,就是麻烦一些。
什么是幂等操作
有一些HTTP方法,如:GET,不管你使用多少次它都能产生相同的结果,在没有任何一边影响的情况下,发送多个 GET 请求到相同的URI 将会产生相同的响应结果。因此,这就是所谓幂等操作。换句话说,POST方法不是幂等操作 ,因为如果发送多个 POST 请求,它将在服务端创建不同的资源。但是,假如你用PUT更新资源,它将是幂等操作。
注解
@Controller
@Controller 注解,它将一个类标记为 Spring Web MVC 控制器 Controller 。
@RestController
@RestController 注解,在 @Controller 基础上,增加了 @ResponseBody 注解,更加适合目前前后端分离的架构下,提供 Restful API ,返回例如 JSON 数据格式。当然,返回什么样的数据格式,根据客户端的 "ACCEPT" 请求头来决定。
@RequestMapping
用于将特定 HTTP 请求方法映射到将处理相应请求的控制器中的特定类/方法,此注释可应用于两个级别:类级别:映射请求的 URL。方法级别:映射 URL 以及 HTTP 请求方法。
@GetMapping
@RequestMapping 可注解在类和方法上;@GetMapping 仅可注册在方法上。@RequestMapping 可进行 GET、POST、PUT、DELETE 等请求方法;@GetMapping 是 @RequestMapping 的 GET 请求方法的特例,目的是为了提高清晰度。
SpringMVC流程
1.发送请求
用户向服务器发送 HTTP 请求,请求被 Spring MVC 的调度控制器 DispatcherServlet 捕获。
2.映射处理器
DispatcherServlet 根据请求 URL ,调用 HandlerMapping 获得该 Handler 配置的所有相关的对象(包括 Handler 对象以及 Handler 对象(包含了我们请求的Controller类和Method方法的对象)对应的拦截器),最后以 HandlerExecutionChain 对象的形式返回。
3.处理器适配器
DispatcherServlet 根据获得的 Handler,选择一个合适的HandlerAdapter。(如果成功获得HandlerAdapter,此时将开始执行拦截器的preHandler(..)方法)
4.执行Handler
提取请求 Request 中的模型数据,填充 Handler 入参,开始执行Handler(Controller)。在填充Handler的入参过程中,根据你的配置,Spring 将帮你做一些额外的工作。Handler(Controller) 执行完成后,向 DispatcherServlet 返回一个 ModelAndView 对象。 额外工作: HttpMessageConverter :会将请求消息(如 JSON、XML 等数据)转换成一个对象。 数据转换:对请求消息进行数据转换。如 String 转换成 Integer、Double 等。 数据格式化:对请求消息进行数据格式化。如将字符串转换成格式化数字或格式化日期等。 数据验证: 验证数据的有效性(长度、格式等),验证结果存储到 BindingResult 或 Error 中。
5.解析视图
Handler(Controller)执行完毕后,向 DispatcherServlet 返回一个ModelAndView 对象。根据返回的 ModelAndView ,选择一个适合的 ViewResolver(必须是已经注册到 Spring 容器中的 ViewResolver),解析出 View 对象,然后返回给 DispatcherServlet。、
6,7.渲染视图 + 响应请求
ViewResolver 结合 Model 和 View,来渲染视图,并写回给用户( 浏览器 )。
PS(前后端分离)
对于目前主流的架构,前后端已经进行分离了,所以 Spring MVC 只负责 Model 和 Controller 两块,而将 View 移交给了前端。所以,在上图中的步骤 ⑤ 和 ⑥ 两步,已经不在需要。如果 Handler(Controller) 执行完后,如果判断方法有 @ResponseBody 注解,则直接将结果写回给用户( 浏览器 )。但是 HTTP 是不支持返回 Java POJO 对象的,所以需要将结果使用 HttpMessageConverter 进行转换后,才能返回。例如说,大家所熟悉的 FastJsonHttpMessageConverter ,将 POJO 转换成 JSON 字符串返回。
核心
Handler
从2个Handler中,找到合适控制器。
XML的配置方式的控制器
BeanNameUrlHandlerMapping@833153a
注解方式的控制器
RequestMappingHandlerMapping@3602f818
Adapter
从3个Adapter中找到合适的处理器
XML方式
HttpRequestHandlerAdapter
SimpleControllerHandlerAdapter
注解方式
annotation.RequestMappingHandlerAdapter
spring事务管理
事务管理的设计
配置事务管理
application.xml
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
数据源事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean>
声明事务
使用注解定义事务
<tx:annotation-driven transaction-manager="transactionManager"/>
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.READ_COMMITTED)
XML配置事务
配置事务切面
<aop:config> <aop:pointcut id="serviceOperation" expression="execution(* com.hly.ssm.service.*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation" /> </aop:config>
配置事务通知属性
<tx:advice id="txAdvice" transaction-manager="transactionManager"> <!-- 定义事务传播属性 --> <tx:attributes> <tx:method name="insert*" propagation="REQUIRED" /> <tx:method name="select*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED"/> <tx:method name="get*" propagation="REQUIRED" read-only="true" /> <tx:method name="*" propagation="REQUIRED" read-only="true" rollback-for="Exception"/> </tx:attributes> </tx:advice>
tx:method属性
name
与事务属性关联的方法名。通配符(*)可以用来指定一批关联到相同的事务属性的方法。 如:'select*'、'delect*'、'insert*'等等。
必要
propagation
事务传播行为,默认REQUIRED
不必要
isolation
事务隔离级别,默认DEFAULT
不必要
timeout
事务超时的时间(以秒为单位),默认-1
不必要
read-only
事务是否只读,默认false
不必要
rollback-for
被触发进行回滚的 Exception(s),逗号隔开
不必要
no-rollback-for
不被触发进行回滚的 Exception(s),逗号隔开
不必要
数据库相关知识
ACID特性
原子性
要么全部完成,要么全部不完成
一致性
事务始终保持系统处于一致的状态
隔离性
两个事务之间的隔离程度
持久性
事务完成,更改持久保存在数据库中
丢失更新
隔离级别
4层定义
脏读
可以读取未提交的事务
读/写提交
一个事务只能读取另一个事务已经提交的数据
可重复读
同一条数据库事务的读/写按照一个序列化进行操作
序列化
按照顺序读写,消除数据库事务之间并发产生数据不一致问题
作用
不同程度上减少丢失更新
选择
脏读到序列化,性能直线下降
读/写提交试用在大部分场景
数据库
mysql默认可重复读
oracle默认读/写提交
传播行为
REQUIRED
如果有事务在运行,当前的方法就在这个事务内运行,否则就启动一个新的事务,并在自己的内行
SUPPORTS
如果有事务在运行,当前的方法就在这个事务内运行,否则它可以不运行在事务中
MANDATORY
当前的方法必须运行在事务内部,如果没有正在运行的事务,就抛出异常
REQUIRES_NEW
当前的方法必须启动新事务,并在他自己的事务内部运行,如果有事务在运行,应该将它挂起
NOT_SUPPORTED
当前的方法不应该运行在事务中,如果有运行的事务,应将它挂起
NEVER
当前的方法不应该运行在事务中,如果有运行的事务,就抛出异常
NESTED
嵌套事务,调用方法抛出异常只会回滚自己内部执行的SQL,不会回滚主方法SQL