Spring
一、基本概念
1、Spring优点
1、轻量级、非侵入式的框架;对现有的类结构没有影响
2、可以提供众多服务,如事务管理、WS(WebService)等
3、AOP很好支持、方便面向切面编程、将业务逻辑和系统服务分开
4、对主流的框架提供了很好的集成支持,如hibernate、Struts2、JPA等,像一个胶水一样,把一些好的框架粘合在一起方便使用
5、使用Spring的IOC容器,将对象之间的依赖关系交给Spring,降低组件之间的耦合性,让我们更专注于应用逻辑代码
6、Spring DI机制降低了业务对象替换的复杂性。
7、Spring的高度可开放性,并不强制依赖于Spring,开发者可以自由选择Spring部分或全部
复制代码
2、Spring缺点
1、缺少一个公用控制器
2、没有SpringBoot好用
3、Spring像一个胶水,将框架黏在一起,后面拆分的话就不容易拆分了
复制代码
3、什么是DI机制
依赖注入(Dependecy Injection)和控制反转(Inversion of Control)是同一个概念,具体的讲:当某个角色需要另外一个角色协助的时候,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在spring中创建被调用者的工作不再由调用者来完成,因此称为控制反转。创建被调用者的工作由spring来完成,然后注入调用者因此也称为依赖注入
复制代码
二、Aop
1、基本概念
1、核心业务功能和切面功能分别独立进行开发 ,然后把切面功能和核心业务功能 "编织" 在一起,这就叫AOP
2、让关注点代码与业务代码分离(各个步骤之间良好的隔离性、源代码无关性)
3、面向切面编程就是指: 对很多功能都有的重复的代码抽取,再在运行的时候往业务方法上动态植入“切面类代码”。
4、应用场景:日志,事务管理,权限控制
复制代码
2、实现原理
- jdk动态代理
主要通过Proxy.newProxyInstance()和InvocationHandler这两个类和方法实现
-
cglib
生成对象类型为Enhancer
实现原理类似于 jdk 动态代理,只是他在运行期间生成的代理对象是针对目标类扩展的子类
-
静态代理
在编译的时候就直接生成代理类
缺点:如果要代理一个接口的多个实现的话需要定义不同的代理类
代理类 和 被代理类 必须实现同样的接口,万一接口有变动,代理、被代理类都得修改 -
jdk和cglib的对比
3、配置方式
-
XML方式
-
注解方式
-
基于JAVA类配置
通过 @Configuration 和 @Bean 这两个注解实现的
@Configuration 作用于类上,相当于一个xml配置文件;
@Bean 作用于方法上,相当于xml配置中的bean;
三、IOC
1、依赖注入
-
装配方式(依赖注入的具体行为)
i、基于注解的自动装配
注解:
@Autowired(byType)+@Qualifier
@Resource(byName)
自动扫描:
component-scan
ii、基于XML配置的显式装配
iii、基于Java配置的显式装配
能在编译时就发现错误
-
依赖注入的方式
i、构造器方式注入
构造器依赖注入通过容器触发一个类的构造器来实现的,该类有一系列参数,每个参数代表一个对其他类的依赖。
例如:<bean id="hello" class="com.maven.Hello"><property name="text" ref="text" /></bean> 复制代码
ii、settter方法注入
之所以叫setter方法注入,因为这是通过找到类的对应的setter方法,再进行相应的注入
Setter方法注入是容器通过调用无参构造器或无参static工厂 方法实例化bean之后,调用该bean的setter方法,即实现了基于setter的依赖注入。
iii、最好的解决方案是
用构造器参数实现强制依赖,setter方法实现可选依赖
-
循环依赖
i、构造器方式无法解决,只能抛出异常ii、多例方式无法解决,只能抛出异常
因为Spring容器不缓存”prototype”作用域的bean,因此无法提前暴露一个创建中的bean。
iii、单例模式可以解决
通过提前暴露一个单例工厂方法,从而使其他bean能够引用到该bean提前暴露一个正在创建中的bean
iiii、不用创建对象,而只需要描述它如何被创建,不在代码里直接组装组件和服务,但是要在配置文件里描述哪些组件需要哪些服务,之后一个容器(IOC容器)负责把他们组装起来。
2、容器的初始化过程
1.Resource定位;指对BeanDefinition的资源定位过程。通俗地讲,就是找到定义Javabean信息的XML文件,并将其封装成Resource对象。
2.BeanDefinition的载入;把用户定义好的Javabean表示为IoC容器内部的数据结构,这个容器内部的数据结构就是BeanDefinition。
3.向IoC容器注册这些
BeanDefinition。
3、bean知识
- bean的生命周期
2. bean的作用域
1). singleton
singleton是Bean的默认作用域
默认情况下是容器初始化的时候创建,但也可设定运行时再初始化bean
DefaultSingletonBeanRegistry类里的singletonObjects哈希表保存了单例对象。
Spring IoC容器中只会存在一个共享的Bean实例,无论有多少个Bean引用它,始终指向同一对象。
Spring容器可以管理singleton作用域下bean的生命周期,在此作用域下,Spring能够精确地知道bean何时被创建,何时初始化完成,以及何时被销毁
复制代码
2). prototype
每次通过Spring容器获取prototype定义的bean时,容器都将创建一个新的Bean实例,每个Bean实例都有自己的属性和状态
当容器创建了bean的实例后,bean的实例就交给了客户端的代码管理,Spring容器将不再跟踪其生命周期,并且不会管理那些被配置成prototype作用域的bean的生命周期。
对有状态的bean使用prototype作用域,而对无状态的bean使用singleton作用域。
复制代码
3). request
在一次Http请求中,容器会返回该Bean的同一实例。而对不同的Http请求则会产生新的Bean,而且该bean仅在当前Http Request内有效。
复制代码
4). session
在一次Http Session中,容器会返回该Bean的同一实例。而对不同的Session请求则会创建新的实例,该bean实例仅在当前Session内有效。
复制代码
5). global Session
在一个全局的Http Session中,容器会返回该Bean的同一个实例,仅在使用portlet context时有效。
复制代码
-
bean的创建
1.进入getBean()方法 2.判断当前bean的作用域是否是单例,如果是,则去对应缓存中查找,没有查找到的话则新建实例并保存。如果不是单例,则直接新建实例(createBeanInstance) 3.新建实例后再将注入属性(populateBean),并处理回调 1).创建bean 2).找到@Autowired的对象 3).创建注入对象,并赋值 复制代码
4、大致流程
四、事务管理
1、基本概念
如果需要某一组操作具有原子性,就用注解的方式开启事务,按照给定的事务规则来执行提交或者回滚操作
事务管理一般在Service层
2、事务控制
编程式事务控制(用户通过代码的形式手动控制事务)
1).Conn.setAutoCommite(false); // 设置手动控制事务
2).粒度较细,比较灵活,但开发起来比较繁琐: 每次都要开启、提交、回滚
复制代码
声明式事务控制(Spring提供对事物的控制管理)
1).XML方式
2).注解方式
复制代码
3、事务属性
-
事务传播行为
required_new:如果当前方法有事务了,当前方法事务会挂起,在为加入的方法开启一个新的事务,直到新的事务执行完、当前方法的事务才开始
required(默认方法):如果当前方法已经有事务了,加入当前方法事务
其余五种方式(拓展学习)
事务传播行为用来描述由某一个事务传播行为修饰的方法被嵌套进另一个方法的时候事务如何传播。
-
数据库的隔离级别(参考隔离级别的那篇文章)
-
事务超时属性
指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。
-
事务只读属性
对事物资源是否执行只读操作
-
回滚规则
定义了哪些异常会导致事务回滚而哪些不会。默认情况下,事务只有遇到运行期异常时才会回滚,而在遇到检查型异常时不会回滚,也可以用用户自己定义
4、Spring事务管理接口
PlatformTransactionManager
TransactionDefinition
TransactionStatus
5、事务管理一般在Service层
如果在dao层,回滚的时候只能回滚到当前方法,但一般我们的service层的方法都是由很多dao层的方法组成的
如果在dao层,commit的次数会过多
五、SpringMVC
1、执行流程
2、注解
3、servlet生命周期
1.加载和实例化
2.初始化
3.请求处理
4.服务终止