spring笔记
第一部分:spring概述
1.1 从整体上来说(概述)
我们常说的Spring其实指的是Spring FrameWork(Spring框架),Spring是分层的full-stack(全栈)轻量级开源框架,以IOC和AOP为内核,提供了展现层springMVC和业务层事务管理等众多的企业级应用技术,还能整合开源的第三方框架和类库。
1.2 Spring优势
整个Spring的优势,传达出一个信号,Spring是一个综合的,且有很强的思想性框架,每学习一天,就能体会到它的一些优势。
1.3 Spring的核心结构
Spring包括以下几个大模块:
- Spring核心容器Core Container:它管理Spring应用中bean的创建、配置和管理,所有Spring模块都构建与核心容器之上。
- 面向切面编程AOP/Aspects
- 数据访问Data Access
- web
- test
第二部分:Spring的核心思想
2.1 IOC
2.1.1 什么是IOC
IOC(Inversion of control)控制反转,是一种技术思想。
解决java领域对象的创建,管理所造成的对象之间的耦合问题。在IOC思想下开发,不需要再去显示的new对象了,而是由IOC容器帮助我们实例化对象并且管理它,我们需要哪个对象,就去问IOC容器要即可。
2.1.2 IOC和DI的区别
DI(Dependency Injection)依赖注入
IOC和DI描述的是同一件事情,只不过角度不同罢了:
IOC是站在对象的角度,对象的实例化和管理的权利交给了(反转给了)容器
DI是站在容器的角度,容器会把对象依赖的其它对象注入
2.2 AOP
2.2.1 什么是AOP
AOP(Aspect oriented Programming)面向切面编程
AOP是OOP的延续(封装,继承,多态)
2.2.2 AOP解决什么问题
AOP解决了在不改变原有代码逻辑的基础上,增强横切代码逻辑,根本上解耦合,避免横切代码重复。
第三部分:手写IOC和AOP
3.1 new创建对象的问题
实例化对象除了new之外,还有反射技术!Class.forName("全限定类名"),可把全限定类名配置在xml中。
另外,使用工厂模式通过反射技术生产对象,工厂模式是解耦合非常好的一种模式。
3.2 service层事务控制问题
数据库事务归根结底是Connection的事务:connection.commit()提交事务;connection.rollback()回滚事务。
开启事务就是关闭Connection的自动提交connection.autoCommit(false);
让多次更新操作使用同一个connection连接,并且在同一个线程内执行(我们可以给当前线程ThreadLocal绑定一个connection,和当前线程有关系的数据库操作都会使用这个connection)
(第一次使用连接,发现当前线程没有,从连接池获取一个连接绑定到当前线程)
3.3 用到的设计模式
3.3.1 工厂模式(BeanFactory使用反射技术创建对象)
1)简单工厂模式(静态工厂/实例工厂):根据不同的传参创建不同的对象
使用场景:1.当客户程序不需要知道要使用对象的创建过程;2)客户程序使用的对象存在变动的可能,或者根本就不知道要使用哪一个具体的对象。
2)工厂方法:一个工厂只创建一个对应的对象
3.3.2 单例模式(获取当前线程的数据库连接,事务管理类等)
私有化构造方法,提供对外获取实例的静态接口
1)饿汉式
2)懒汉式(加synchronized关键字进行同步)
3.3.3 代理模式(主要用于增强逻辑,如事务逻辑)
1)静态代理:每个委托对象会对应一个实实在在的代理类
2)动态代理:不需要为每个委托对象都创建一个代理类
分为JDK动态代理:委托对象必须要实现接口
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[]
args) throws Throwable {
method.invoke(target,args);
}
});
Cglib动态代理(需要引入第三方jar包):委托对象不需要实现接口
Enhancer.create()
3.4 ThreadLocal关键字
它代表一个线程局部变量,通过把数据放在ThreadLocal中就可以让每个线程创建一个该变量的副本,
从而避免并发访问的线程安全问题。
第四部分:Spring IOC应用
4.1 Spring IOC基础
4.1.1 BeanFactory和ApplicationContext区别
BeanFactory(IOC容器的基础接口):通过反射技术实例化对象并维护对象之间的关系
ApplicationContext(IOC容器的高级接口)基于xml和注解的三个常用实现类:
ClassPathXmlApplicationContext;FileSystemXmlApplicationContext;AnnotationConfigApplicationContext
4.1.2 启动 IoC 容器的方式:
1)java环境下启动IOC容器(3种)
ClassPathXmlApplicationContext;FileSystemXmlApplicationContext;AnnotationConfigApplicationContext
2)web环境下启动IOC容器:ContextLoaderListener(监听器加载xml或注解配置类)
告诉ContextloaderListener知道我们使⽤注解的⽅式启动ioc容器-->
contextClass
org.springframework.web.context.support.AnnotationConfigWebAppli
cationContext
4.1.3 实例化bean的三种方式:
1)使用无参构造方法;2)使用静态方法创建;3)使用实例化方法创建
4.1.4 Bean的作用范围及生命周期
在Spring框架管理Bean对象的创建时,Bean对象默认都是单例的
作用范围:
单例Singleton:当创建容器时,对象就被创建了,单例模式的生命周期与容器相同
多例(原型)模式:当使用对象时,创建新的对象实例,只要对象在使用中,就一直活着,当对象长时间不用时,被java的垃圾回收器回收了;
多例模式下的bean对象,spring框架只负责创建,不负责销毁。
4.1.5 纯注解模式
4.2 IOC高级特性
4.2.1 延迟加载lazy-init
bean对象创建的延迟加载
普通bean的初始化是在容器启动初始化阶段执行的,而被lazy-init=true修饰的bean则是从容器里第一次执行context.gteBean()时进行触发。
Spring 启动的时候会把所有bean信息(包括XML和注解)解 析转化成Spring能够识别的BeanDefinition并存到Hashmap里供下面的初始化时用,然后对每个 BeanDefinition 进行处理,如果是懒加载的则在容器初始化阶段不处理,其他的则在容器初始化阶段进 行初始化并依赖注入。
4.2.2 FactoryBean 和 BeanFactory
spring中有两种bean,一个普通bean,一个工厂bean
factoryBean可以生成某一个类型的bean实例,借助于它实现自定义bean的过程,应用于复杂对象的创建
测试,获取FactoryBean,需要在id之前添加“&”
4.2.3 后置处理器
spring提供了两种后处理bean的接口:BeanPostProcessor和BeanFactoryPostProcessor
工厂初始化(BeanFactory)—> Bean对象 在BeanFactory初始化之后可以使用BeanFactoryPostProcessor进⾏后置处理做⼀些事情 在Bean对象实例化(并不是Bean的整个⽣命周期完成)之后可以使⽤BeanPostProcessor进⾏后置处 理做⼀些事情 注意:对象不⼀定是springbean,⽽springbean⼀定是个对象
Spring启动过程过程中,会把Bean解析成Spring内部的BeanDefinition
注意:调⽤ BeanFactoryPostProcessor ⽅法时,这时候bean还没有实例化,此时 bean 刚被解析成 BeanDefinition对象
4.2.4 IOC循环依赖问题
循环依赖其实就是循环引用,也就是两个或两个以上的bean相互引用对方,形成闭环。
Spring中循环依赖场景:
1)构造器的循环依赖(构造器注入)
2)Filed属性的循环依赖(set注入)
其中,构造器的循环依赖问题无法解决,只能抛出BeanCurrentlyInCreationException异常,
在解决属性循环依赖时,Spring采用的是提前暴露对象的方法。
总结:Spring 不支持原型 bean 的循环依赖。
第五部分:Spring源码分析
5.1 IOC容器初始化过程
下⾯我们以 ClasspathXmlApplicationContext 为例,深⼊源码说明 IoC 容器的初始化流程
Spring IoC 容器初始化的关键环节就在 AbstractApplicationContext#refresh() ⽅法中
我们查看 refresh ⽅法来俯瞰容器创建的主体流程
Spring IoC容器初始化主流程如下:
第六部分:AOP应用
6.1 AOP术语
JoinPoint连接点:指方法开始、结束、异常、正常运行完毕等这些特殊的时机点(候选点)
PointCut切入点:指AOP要影响的方法
Advice通知/增强:提供增强功能的方法:前置通知、后置通知、异常通知、最终通知、环绕通知
Target目标对象:被代理对象
Proxy:代理对象
Weaving织入:把增强应用到目标对象创建新的代理对象的过程
Aspect切面:增强代码所关注的方法,把增强代码定义到一个类中,这个类就是切面类。
6.2 AOP代理选择
无论被代理对象是否实现接口,只要不是final修饰的类都可以采用cglib提供的方式创建代理对象
Cglib:基于子类的动态代理
6.3 Spring声明式事务的支持
编程式事务:在业务代码中添加事务控制代码
声明式事务:通过xml或者注解配置的方式达到事务控制的目的
6.3.1 事务的四大特性
原子性,一致性,隔离性,持久性
6.3.2 事务的四种隔离级别(解决事务并发问题)
不考虑隔离级别,会出现:脏读(读到未提交数据)、不可重复读(读到已提交的update数据)、虚读(幻读)(读到已提交的insert或delete数据)
6.3.3 事务的传播行为
A调用B,我们站在B的角度来观察定义事务的传播行为
1)Propagation_required(常用):如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
2) Propagation_supports:支持当前事务,如果当前没有事务,就以非事务方式执行。
3) Propagation_mandatory:使⽤当前的事务,如果当前没有事务,就抛出异常。
4) Propagation_requires_new:新建事务,如果当前存在事务,把当前事务挂起。
5) Propagation_not_supported:以⾮事务⽅式执⾏操作,如果当前存在事务,就把当前事务挂起。
6) Propagation_never:以⾮事务⽅式执⾏,如果当前存在事务,则抛出异常。
7) Propagation_nested:如果当前存在事务,则在嵌套事务内执⾏。如果当前没有事务,则执⾏与PROPAGATION_REQUIRED类似的操作。
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
纯注解方式:在 Spring 的配置类上添加 @EnableTransactionManagement 注解即可
第七部分:AOP源码分析