1. Spring 特征
Spring 是一个轻量级容器(Container), 只要由IOC 和 AOP组成; 又叫控制反转和面向切面
2. Spring 核心组件
3. Spring 常用模块
4. Spring 中主要的包
Spring AOP:Spring的面向切面编程,提供AOP(面向切面编程)的实现
Spring Aspects:Spring提供的对AspectJ框架的整合
Spring Beans:Spring IOC的基础实现,包含访问配置文件、创建和管理bean等。
Spring Context:在基础IOC功能上提供扩展服务,此外还提供许多企业级服务的支持,有邮件服务、任务调度、JNDI定位,EJB集成、远程访问、缓存以及多种视图层框架的支持。
Spring Context Support:Spring context的扩展支持,用于MVC方面。
Spring Core:Spring的核心工具包
Spring expression:Spring表达式语言
Spring Framework Bom:浏览对象支持
Spring Instrument:Spring对服务器的代理接口
Spring Instrument Tomcat:Spring对tomcat连接池的集成
Spring JDBC:对JDBC 的简单封装
Spring JMS:为简化jms api的使用而做的简单封装
Spring Messaging:集成messaging api和消息协议提供支持
Spring orm:整合第三方的orm实现,如hibernate,ibatis,jdo以及spring 的jpa实现
Spring oxm:Spring对于object/xml映射的支持,可以让JAVA与XML之间来回切换
Spring test:对JUNIT等测试框架的简单封装
Spring tx:为JDBC、Hibernate、JDO、JPA等提供的一致的声明式和编程式事务管理。
Spring web:包含Web应用开发时,用到Spring框架时所需的核心类,包括自动载入WebApplicationContext特性的类、Struts与JSF集成类、文件上传的支持类、Filter类和大量工具辅助类。
webmvc:包含SpringMVC框架相关的所有类。包含国际化、标签、Theme、视图展现的FreeMarker、JasperReports、Tiles、Velocity、XSLT相关类。当然,如果你的应用使用了独立的MVC框架,则无需这个JAR文件里的任何类。
Spring webmvc portlet:Spring MVC的增强
5. Spring 常用注解
6. Spring 第三方结合
7. Spring IOC原理
1. IOC 容器实现
BeanFactory -- 框架基础设施
- BeanDefinitionRegistry 注册表 ---- 注册 Bean Definition
- BeanFactory ---- 主要用于 获取Bean, getBean(String beanName)
- ListableBeanFactory ---- 主要用于 查看Bean的个数, 获取Bean配置名,查看Container中是否有Bean的方法
- HierarchicalBeanFactory 父子级联 ---- 建立Container里的层级体系, 将 Controller,Service,Dao的Bean分开
- ConfigurableBeanFactory ---- 增强IOC的可定制性, 包括类装载,属性编辑器,容器初始化
- AutowireCapableBeanFactory ---- Bean自动装配的工厂
- SingletonBeanRegistry 单例Bean的注册 ---- 用单例模式存储Bean,第二次拿Bean只需要从IOC缓存中拿取了
- 依赖日志框架 ---- 必须要在ClassPath下提供Log4J,Spring容器才不会报错
Bean Definition 过程又分为4步:
实例化(Instantiation) ---- 属性赋值(Populate) ---- 初始化(Initialization) ---- 销毁(Destruction)
ApplicationContext -- 面向开发应用
ApplicationContext 是 BeanFactory 的子类, 因此他继承了 HierarchicalBeanFactory 和 ListableBeanFactory 等接口
从 ApplicationContext 还衍生出很多 Context:
- ClassPathXmlApplicationContext ---- 默认从类路径加载配置文件
- FileSystemXmlApplicationContext ---- 默认从文件系统中装载配置文件
- ApplicationEventPublisher ---- 让Container拥有发布ApplicationContext的能力,包括启动event, 关闭event等
- MessageSource ---- 为 Application 提供消息访问功能
- ResourcePatternResolver ---- 通过带前缀的Ant风格ClassPath加载Spring 配置文件
- LifeCycle ---- 操作 ApplicationContext 的 start/stop 进行调度达到每一个Life State
- ConfigurableApplicationContext ---- 增加了 refresh() 和 close(), 让 Application 可以启动刷新关闭Context
WebApplication -- 体系架构
2. Spring Bean 作用域
- singleton 单例: IOC只会有一个共享Bean的 Instance
- prototype 原型: container 每次获取prototype定义的Bean, 都会创建一个新的Instance
- request: 在 http request 中返回Bean的Instance,request结束, Instance也会destroy (仅在http request中有效)
- session: 在 http session 中返回Bean的Instance,session结束,Instance也会destroy (仅在http session中有效)
- global session: 与上面类似,只在 global session中有效
3. Spring Bean LifeCycle 生命周期
- 实例化: new Instance()
- IOC DI注入: 按照Spring Context 对Bean进行配置生成Instance
- setBeanName 实现: 前提是这个Bean已经实现了BeanNameAware, 然后调用setBeanName(bean_id)
- BeanFactoryAware 实现: 前提是这个Bean已经实现了BeanFactoryAware, 然后调用setBeanFactory(BeanFactory)
- ApplicationContextAware 实现: 前提是这个Bean已经实现了ApplicationContextAware,然后调用setApplicationContext
- postProcessBeforeInitialization 实现: 前提是这个Bean关联了BeanPostProcessor, 调用postProcessBeforeInitialization
- init-method: 如果 Spring Configuration 配置了init-method属性便会自动调用初始化方法
- postProcessAfterInitialization: 和 postProcessBeforeInitialization一样需要关联 BeanPostProcessor
- Destroy: 当Bean不再需要,如果这个Bean实现了DisposableBean,就会调用 Destroy方法
- destroy-method: 如果Spring Configuration 配置了destroy-method, 就会调用配置中的destroy-method
- init-method/destroy-method:可以自行定制init-method/destroy-method 也可以用@PostConstruct 和 @PreDestroy
4. Spring DI 依赖注入的四种方式
- 构造器注入: Java OOP 中的Constructor进行注入
- Setter方法注入: Java OOP 中的 setObject 方法进行注入
- 静态工厂注入: 创建一个StaticFactory 类然后return 一个 Instance;
- 实例工厂: 创建一个Factory(non-static) 类然后return 一个 Instance;
5. 5种不同方式的自动装配
- no: 不自动装配; 通过设置ref属性进行装配
- byName: 通过参数名进行装配;此时 autowire 设置为 byName
- byType: 通过参数类型进行装配;此时 autowire 设置为 byType
- constructor: 通过构造器进行装配, 需要提供构造器 parameters
- autodetect: 优先用Constructor 自动装配, 如果无法工作,则使用 byType方式
8. Spring AOP原理
AOP 称为面向切面编程;AOP包括核心关注点和横切关注点
核心关注点: 核心关注点指的是业务相关的关注点 横切关注点: 包括 权限认证、日志、事物等
AOP主要应用场景:
- Authentication 权限
- Caching 缓存
- Context passing 内容传递
- Error handling 错误处理
- Lazy loading 懒加载
- Debugging 调试
- logging, tracing, profiling and monitoring 记录跟踪 优化 校准
- Performance optimization 性能优化
- Persistence 持久化
- Resource pooling 资源池
- Synchronization 同步
- Transactions 事务
AOP 核心概念:
- aspect 切面: 横切关注点的抽象
- 横切关注点: 这些关注点对method进行拦截,拦截之后再进行处理
- joinpoint 连接点: 被拦截到的点 (包括方法,字段,构造器)
- 切入点: 对joinpoint 进行拦截的定义
- 通知: 拦截到joinpoint后要执行的代码; 分为 前置,后置,异常,最终,环绕通知
- 目标对象: 代理的 目标对象
- weave 织入: 将aspect用到目标对象上从而导致代理对象创建的一整个过程
- introduction 引入: 不修改代码并在运行期为类动态添加一些方法和字段
AOP 通知类型:
- Before Advice 前置: 在 joinpoint之前执行的通知,不能阻止joinpoint之前的执行流程
- After returning Advice 后置: 在 joinpoint 之后执行的通知
- After throwing Advice 异常: 在method throw出来exception时执行的通知
- After (finally) Advice 最终: 在 joinpoint 退出的时候执行的通知(不论是正常返回还是异常退出)
- Around Advice 环绕通知: 包围一个 joinpoint的通知,如方法调用
AOP 代理方式:
如果是 interface相关 就会使用JDK,如果是其他就会使用CGLIB (全称: Code Generation Library)
- JDK 动态代理: 涉及到 Proxy 和 InvocationHandler; 用反射调用类并且动态把aspect和业务weave在一起
- CGLIB 代理: CGLIB封装了asm, 可以在运行期动态生成 new class
9. Spring MVC原理
- Http 请求 到 DispatcherServlet: 客户端请求提交到 DispatchServlet
- HandlerMapping 寻找处理器: DispatcherServlet控制器查询HandlerMapping找到处理请求的Controller
- 调用处理器 Controller: DispatcherServlet 将请求提交到 Controller
- Controller 调用业务逻辑处理后,返回 ModelAndView
- DispatcherServlet 查询 ModelAndView: DispatcherServlet 查询多个ViewResolver 找到ModelAndView指定的view
- ModelAndView 反馈 Http: 是一个返回view结果的 http response
10. Spring Boot原理
- 创建独立的Spring Application
- 嵌入的 Tomcat 不需要部署 WAR文件
- 简化 Maven 配置
- 自动配置 Spring
- 提供生产就绪型功能,如指标,健康检查Actuator 和 外部配置
- 绝对没有代码生成和对XML没有配置要求
11. Spring JPA原理
事务的原理
事务 Transaction 保证有 Acid特性,即 Atomicity, Consistency, Isolation 和 Durability
本地事务
只局限于当前事务资源,不支持多 datasource的 分布式事务
代码语言:javascript复制public void transferAccount () {
Connection conn = null;
Statement stmt = null;
try{
conn = getDataSource().getConnection();
// 将自动提交设置为 false,若设置为 true 则数据库将会把每一次数据更新认定为一个事务并自动提交
conn.setAutoCommit(false);
stmt = conn.createStatement();
// 将 A 账户中的金额减少 500
stmt.execute("update t_account set amount = amount - 500 where account_id = 'A'");
// 将 B 账户中的金额增加 500
stmt.execute("update t_account set amount = amount 500 where account_id = 'B'");
// 提交事务
conn.commit();
// 事务提交:转账的两步操作同时成功
} catch(SQLException sqle){
// 发生异常,回滚在本事务中的操做
conn.rollback();
// 事务回滚:转账的两步操作完全撤销
stmt.close();
conn.close();
}
}
分布式事务
拥有 Transaction Manager 支持多个 datasource
代码语言:javascript复制public void transferAccount() {
UserTransaction userTx = null;
Connection connA = null; Statement stmtA = null;
Connection connB = null; Statement stmtB = null;
try{
// 获得 Transaction 管理对象
userTx = (UserTransaction)getContext().lookup("java:comp/UserTransaction");
connA = getDataSourceA().getConnection();// 从数据库 A 中取得数据库连接
connB = getDataSourceB().getConnection();// 从数据库 B 中取得数据库连接
userTx.begin(); // 启动事务
stmtA = connA.createStatement();// 将 A 账户中的金额减少 500
stmtA.execute("update t_account set amount = amount - 500 where account_id = 'A'");
// 将 B 账户中的金额增加 500
stmtB = connB.createStatement();
stmtB.execute("update t_account set amount = amount 500 where account_id = 'B'");
userTx.commit();// 提交事务
// 事务提交:转账的两步操作同时成功(数据库 A 和数据库 B 中的数据被同时更新)
} catch(SQLException sqle){
// 发生异常,回滚在本事务中的操纵
userTx.rollback();// 事务回滚:数据库 A 和数据库 B 中的数据更新被同时撤销
} catch(Exception ne){ }
}
两阶段提交
两阶段提交保证了分布式事务的原子性,第一阶段是准备阶段;第二阶段是提交阶段
- 准备阶段: Transation Manager 对 每一个 source Manager 发送 Prepare, source Manager在本地执行事务但不提交
- 提交阶段: 如果失败则让参与者回滚消息;如果成功则协调者commit之后参与者自行commit或者rollback并释放lock
12. Spring 和 Mybatis 以及 Mybatis 缓存
mybatis 是 Spring 数据库CRUD 的常用工具, 它使用 xml 并自定义sql语句进行CRUD
mybatis缓存: mybatis有两级缓存;第一级缓存是sqlSession缓存默认开启;第二级缓存是跨sqlSession的缓存,mapper级别
Mybatis 一级缓存 (sqlSession级别)
发出一个查询sql, 查询结果以map存储在一级缓存里,key=MapperId offset limit Sql parameters,value=用户信息
同一个sqlsession 再发出相同的sql就会从缓存拿出数据,如果中途出现CUD操作,缓存就会被清空
Mybatis 二级缓存 (mapper级别)
mapper 以 namespace为单位创建缓存,结构还是map
mybatis 的 二级缓存通过 CacheExecutor实现,CacheExecutor会先匹配缓存是否存在不存在才会查询数据库
key: MapperId offset limit Sql parameters
如何启用 二级缓存
- 在 mybatis 全局配置中启用二级缓存配置
- 在 对应的Mapper.xml中配置cache节点
- 在 对应的select 查询节点中添加 useCache=true