1-2.IoC容器设计实现及Spring源码分析.md
阶段一模块二学习笔记-Spring高级框架
[toc]
一、自定义Ioc&AOP框架
1. spring概述
- Spring 简介:Spring 是分层的 full-stack(全栈) 轻量级开源框架,以 IoC 和 AOP 为内核,提供了展现层 SpringMVC 和业务层事务管理等众多的企业级应⽤技术,还能整合开源世界众多著名的第三⽅框架和类库,已经成为使⽤最多的 Java EE 企业应⽤开源框架。
- Spring 的优势
- ⽅便解耦,简化开发
- AOP编程的⽀持
- 声明式事务的⽀持
- ⽅便程序的测试
- ⽅便集成各种优秀框架
- 降低JavaEE API的使⽤难度
- 源码是经典的 Java 学习范例
2. 核心思想
2.1 Ioc
- 什么是IOC: IoC Inversion of Control (控制反转/反转控制),注意它是⼀个技术思想,不是⼀个技术实现
描述的事情:Java开发领域对象的创建,管理的问题
传统开发⽅式:⽐如类A依赖于类B,往往会在类A中new⼀个B的对象
IoC思想下开发⽅式:我们不⽤⾃⼰去new对象了,⽽是由IoC容器(Spring框架)去帮助我们实例化对象并且管理它,我们需要使⽤哪个对象,去问IoC容器要即可 - IOC的作用
IoC解决对象之间的耦合问题 - IOC和DI的区别
IOC和DI描述的是同一件事情(对象实例化及依赖关系维护这件事情),只不过角度不同罢了
IOC是站在对象的角度:对象实例化及其管理的权利交给了(反转)给了容器
DI是站在容器的角度:容器会把对象依赖的其他对象注入(送进去),比如A对象实例化过程中因为声明了一个B类型的属性,那么就需要容器把B对象注入给A
2.2 AOP
- 先了解OOP
OOP三⼤特征:封装、继承和多态
oop是⼀种垂直继承体系 - OOP问题:
OOP编程思想可以解决⼤多数的代码重复问题,但是有⼀些情况是处理不了的,⽐如下⾯的在顶级⽗类
Animal中的多个⽅法中相同位置出现了重复代码,OOP就解决不了,如图的横切逻辑
- 横切代码重复问题
- 横切逻辑代码和业务代码混杂在⼀起,代码臃肿,维护不⽅便
3.手写IOC和AOP
- 提到工厂模式和单例模式
- 工厂模式:从自己手动创建对象,到自己只传递想要的参数给工厂,由工厂创建对象。
- 单例模式,应用在全局只有一个实例对象时,将自身实例化并赋值给一个属性,加载到此类时直接调用其静态实例。分为懒汉和饿汉式
- 饿汉:
- 懒汉:
- 饿汉:
- 代理模式:实现对方法的前后增强,相当于委托给代理实现想要的功能,代理可以在实现功能的前后实现自己的需求。
- jdk动态代理(需要委托对象实现接口):
- 使用:
- jdk动态代理(需要委托对象实现接口):
3.1银行转账的工厂模式实现
工厂模式生产,在xml中获取实现的全路径进行反射
- 工厂:读取解析xml,通过反射技术实例化对象并且存储待用(map集合);对外提供获取实例对象的接口(根据id获取)
- 存放需要实例化的对象全路径
- 使用工厂中的方法并传入相应参数
- 源码:
git clone -b master1 https://gitee.com/idse666666/my_spring.git
- 存在问题:仍需要从工厂获取bean
- 解决:
- 源码:
git clone -b master2 https://gitee.com/idse666666/my_spring.git
3.2事务控制
- 如图:如果不对service层进行事务控制,将会存在前者转账,后者接收不到的问题。
- 而现有的事务控制是对于每一个数据库连接,我们需要将数据库连接存放到线程中,单个线程只有一个数据库连接,也就是单例模式。
- 经过以上事务控制的拦截,我们捕获存在异常则回滚事务。保证了数据正确。
- 源码:
git clone -b master3 https://gitee.com/idse666666/my_spring.git
- 仍存在问题:我们的每个方法都需要添加开启事务,提交事务,回滚以及try..catch…代码块。应使用代理模式在方法的前后进行增强,将固定的try…catch…代码块提取至jdk动态代理里。
- 源码:
git clone -b master4 https://gitee.com/idse666666/my_spring.git
- 源码:
3.3将所有用到的工具类等以bean形式封装到xml中。
- 源码:
git clone -b master5 https://gitee.com/idse666666/my_spring.git
3.4 手写IOC与AOP示意图
二、 spring IOC应用
1. BeanFactory与ApplicationContext区别
- BeanFactory是Spring框架中IoC容器的顶层接⼝,它只是⽤来定义⼀些基础功能,定义⼀些基础规范,⽽ApplicationContext是它的⼀个⼦接⼝,所以ApplicationContext是具备BeanFactory提供的全部功能的。我们称BeanFactory为SpringIOC的基础容器,ApplicationContext是容器的⾼级接⼝,比BeanFactory要拥有更多的功能
2. 启动IOC的方式
2.1 Java环境下
- ClassPathXmlApplicationContext 从类的根路径下加载配置⽂件(推荐使⽤)
- AnnotationConfigApplicationContext 纯注解模式下启动Spring容器
2.2 Web环境下启动IoC容器
- Web环境下启动IoC容器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--配置Spring ioc容器的配置文件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--使用监听器启动Spring的IOC容器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
3. 使用spring ioc xml形式注入Bean改造手写的ioc和aop
3.1 常见的bean标签:
- id属性: ⽤于给bean提供⼀个唯⼀标识。在⼀个标签内部,标识必须唯⼀。
- class属性:⽤于指定创建Bean对象的全限定类名。
- name属性:⽤于给bean提供⼀个或多个名称。多个名称⽤空格分隔。
- factory-bean属性:⽤于指定创建当前bean对象的⼯⼚bean的唯⼀标识。当指定了此属性之后,class属性失效。
- factory-method属性:⽤于指定创建当前bean对象的⼯⼚⽅法,如配合factory-bean属性使⽤,则class属性失效。如配合class属性使⽤,则⽅法必须是static的。
- scope属性:⽤于指定bean对象的作⽤范围。通常情况下就是singleton。当要⽤到多例模式时,可以配置为prototype。
- init-method属性:⽤于指定bean对象的初始化⽅法,此⽅法会在bean对象装配后调⽤。必须是⼀个⽆参⽅法。
- destory-method属性:⽤于指定bean对象的销毁⽅法,此⽅法会在bean对象销毁前执⾏。它只能为scope是singleton时起作⽤。
3.2 实例化bean的几种方式
1 |
|
3.3 DI依赖注入
1 |
|
- 源码:
git clone -b master6 https://gitee.com/idse666666/my_spring.git
4. xml与注解相结合模式
4.1注意事项
- 实际企业开发中,纯xml模式使⽤已经很少了
- 引⼊注解功能,不需要引⼊额外的jar
- xml+注解结合模式,xml⽂件依然存在,所以,spring IOC容器的启动仍然从加载xml开始
4.2xml中标签与注解的对应(IoC)
DI 依赖注⼊的注解实现⽅式:@Autowired(推荐使⽤)
- 源码:
git clone -b master7 https://gitee.com/idse666666/my_spring.git
5.全注解形式
5.1常用注解
@Configuration 注解,表名当前类是⼀个配置类
@ComponentScan 注解,替代 context:component-scan
@PropertySource,引⼊外部属性配置⽂件
@Import 引⼊其他配置类
@Value 对变量赋值,可以直接赋值,也可以使⽤ ${} 读取资源配置⽂件中的信息
@Bean 将⽅法返回对象加⼊ SpringIOC 容器
5.2 具体迁移所对应形式
- 源码:
git clone -b master8 https://gitee.com/idse666666/my_spring.git
6. 延迟加载
6.1概念
ApplicationContext 容器的默认⾏为是在启动服务器时将所有 singleton bean 提前进⾏实例化。提前
实例化意味着作为初始化过程的⼀部分,ApplicationContext 实例会创建并配置所有的singleton
bean。
6.2使用
1 |
|
6.3 使用场景
- 开启延迟加载⼀定程度提⾼容器启动和运转性能
- 对于不常使⽤的 Bean 设置延迟加载,这样偶尔使⽤的时候再加载,不必要从⼀开始该 Bean 就占⽤资源
7. FactoryBean 和 BeanFactory
7.1概念
- BeanFactory接⼝是容器的顶级接⼝,定义了容器的⼀些基础⾏为,负责⽣产和管理Bean的⼀个⼯⼚,具体使⽤它下⾯的⼦接⼝类型,⽐如ApplicationContext;此处我们重点分析FactoryBean
- Spring中Bean有两种,⼀种是普通Bean,⼀种是⼯⼚Bean(FactoryBean),FactoryBean可以⽣成某⼀个类型的Bean实例(返回给我们),也就是说我们可以借助于它⾃定义Bean的创建过程。
- Bean创建的三种⽅式中的静态⽅法和实例化⽅法和FactoryBean作⽤类似,FactoryBean使⽤较多,尤其在Spring框架⼀些组件中会使⽤,还有其他框架和Spring框架整合时使⽤
7.2 使用
二、 spring AOP应用
- AOP的本质:在不改变原有业务逻辑的情况下增强横切逻辑,横切逻辑代码往往是权限校验代码、⽇志代码、事务控制代码、性能监控代码。
1. AOP相关术语
- 连接点:⽅法开始时、结束时、正常运⾏完毕时、⽅法异常时等这些特殊的时机点,我们称之为连接 点,项⽬中每个⽅法都有连接点,连接点是⼀种候选点
- 切⼊点:指定AOP思想想要影响的具体⽅法是哪些,描述感兴趣的⽅法 Advice增强:
- 第⼀个层次:指的是横切逻辑
- 第⼆个层次:⽅位点(在某⼀些连接点上加⼊横切逻辑,那么这些连接点就叫做⽅位点,描述的是具体 的特殊时机)
- Aspect切⾯:切⾯概念是对上述概念的⼀个综合 Aspect切⾯= 切⼊点+增强= 切⼊点(锁定⽅法) + ⽅位点(锁定⽅法中的特殊时机)+ 横切逻辑 众多的概念,⽬的就是为了锁定要在哪个地⽅插⼊什么横切逻辑代码
2.Spring中AOP的代理选择
- Spring 实现AOP思想使⽤的是动态代理技术
- 默认情况下,Spring会根据被代理对象是否实现接⼝来选择使⽤JDK还是CGLIB。当被代理对象没有实现任何接⼝时,Spring会选择CGLIB。当被代理对象实现了接⼝,Spring会选择JDK官⽅的代理技术,不过我们可以通过配置的⽅式,让Spring强制使⽤CGLIB。
3. AOP的xml实现
1 |
|
- 源码:
git clone -b master9 https://gitee.com/idse666666/my_spring.git
4.AOP的xml+anno形式实现
- 源码:
git clone -b master10 https://gitee.com/idse666666/my_spring.git
5. AOP的anno模式实现
- 源码:
git clone -b master11 https://gitee.com/idse666666/my_spring.git
6. 声明式事务的⽀持
6.1概念
事务指逻辑上的⼀组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功。从⽽确保了数据的准确与安全。又分为
- 编程式事务:在业务代码中添加事务控制代码,这样的事务控制机制就叫做编程式事务
- 声明式事务:通过xml或者注解配置的⽅式达到事务控制的⽬的,叫做声明式事务
6.2事务的四大特性
- 原⼦性(Atomicity) 原⼦性是指事务是⼀个不可分割的⼯作单位,事务中的操作要么都发⽣,要么都不发⽣。从操作的⻆度来描述,事务中的各个操作要么都成功要么都失败
- ⼀致性(Consistency) 事务必须使数据库从⼀个⼀致性状态变换到另外⼀个⼀致性状态。⼀致性是从数据的⻆度来说的,
- 隔离性(Isolation) 事务的隔离性是多个⽤户并发访问数据库时,数据库为每⼀个⽤户开启的事务,每个事务不能被其他事务的操作数据所⼲扰,多个并发事务之间要相互隔离。
- 持久性(Durability) 持久性是指⼀个事务⼀旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发⽣故障也不应该对其有任何影响。
三、 事务
1 事务的隔离级别
不考虑隔离级别会出现:
- 脏读:⼀个线程中的事务读到了另外⼀个线程中未提交的数据。
- 不可重复读:⼀个线程中的事务读到了另外⼀个线程中已经提交的update的数据(前后内容不⼀样)
- 虚读(幻读):⼀个线程中的事务读到了另外⼀个线程中已经提交的insert或者delete的数据(前后条数不⼀样)
四种隔离级别 - Serializable(串⾏化):可避免脏读、不可重复读、虚读情况的发⽣。(串⾏化)
- Repeatable read(可重复读):可避免脏读、不可重复读情况的发⽣。(幻读有可能发⽣) 该机制下会对要update的⾏进⾏加锁
- Read committed(读已提交):可避免脏读情况发⽣。不可重复读和幻读⼀定会发⽣。
- Read uncommitted(读未提交):最低级别,以上情况均⽆法保证。(读未提交)
注意:级别依次升⾼,效率依次降低
2.事务的传播性
- 事务往往在service层进⾏控制,如果出现service层⽅法A调⽤了另外⼀个service层⽅法B,A和B⽅法本身都已经被添加了事务控制,那么A调⽤B的时候,就需要进⾏事务的⼀些协商,这就叫做事务的传播⾏为。A调⽤B,我们站在B的⻆度来观察来定义事务的传播⾏为
3. spring xml实现事务
1 |
|
4. spring xml+anno实现事务
1 |
|
5. 纯注解
1 |
|
- 源码:
git clone -b master12 https://gitee.com/idse666666/my_spring.git
1-2.IoC容器设计实现及Spring源码分析.md
http://example.com/30479.html