面试速记之Spring
目录
- 前言
- IOC
- 容器实现方式
- 对比
- bean管理
- 配置文件方式
- DI
- 注解方式
- 对象创建
- 属性注入
- 完全注解开发
- Spring中bean类型
- bean的作用域
- bean的生命周期
- AOP
- 动态代理
- jdk——需要接口
- cglib——无需接口
- 术语
- 切入点
- 其他
- 事务
- Spring中有两种事务
- Spring事务传播行为
- 隔离级别
- 脏读
- 不可重复读
- 幻读/虚读
前言
本篇内容较繁杂,笔者会根据经验逐步浓缩,力求留下的都是精华。
IOC
降低耦合
把对象创建和对象调用交给Spring
关键点:xml解析、工厂模式、反射
演变过程:
获取bean对象示例
bean有变化只需要修改配置文件信息就ok,代码部分无需修改
反射可以得到类的字节码文件(.class),从而获得类和对象
容器实现方式
ioc思想基于ioc容器(container)实现,它是对象工厂,容器实现的两种方式有:
1.BeanFactory(Spring内部接口,不推荐开发者使用)
2.ApplicationContext(是BeanFactory的子接口,提供更强大的功能给开发者使用)
对比
前者只加载了配置文件,后者还会创建好配置文件中的对象。
看上去第一种比较好(懒加载),但不可否认后者更加方便(程序初始化时就帮全部搞好了)
前者是读硬盘中路径下的xml,后者是读项目路径下的xml,理解为绝对路径和相对路径吧
bean管理
配置文件和注解方式
创建对象和注入属性
配置文件方式
常用属性
id:唯一标识
class:全限定类名
DI
ioc中注入属性的方式
通过setter方法或有参构造函数注入
p名称空间注入可以简化setter注入方式
设置空值和设置特殊符号的方式
外部bean注入示例
内部bean写法
外部bean级联赋值
注入集合类型:
将集合单独抽取出来的以便复用:
注入数据源示例
第一种方式
第二种方式
可通过外部属性文件辅助装配
Spring提供自动装配
开启:使用bean标签的autowire属性,它有两个值byName和byType,分别是通过名称(id)注入和类型(class)注入
注解方式
对象创建
1.引入依赖
2.开启组件扫描(指定扫描范围)
<context:component-scan base-package="com.atguigu"></context:component-scan>
可自定义扫描内容:
3.创建类,在类上添加创建对象注解
Spring提供的注解:
@Component
@Service
@Controller
@Repository
上面四个注解功能一致,都可以用来创建bean实例(默认名称为对应类的首字母小写,可通过设置注解的value值自定义名称)
属性注入
@Autowired:根据属性类型进行自动装配
@Qualifier:根据属性名称进行注入(配合@Autowired使用,适用于有多个实现类的情况)
@Resource:可以根据类型注入,也可以根据名称注入
@Vaule:注入普通类型属性
完全注解开发
配置类代替配置文件(用@Configuration标识配置类)
与xml差异对比
Spring中bean类型
1.普通bean
2.工厂bean
关键区别在于定义的bean的类型与实际拿到的类型是否一致
比如定义Book类只能拿到Book类对象,而定义BookFactory类能够拿到Book类的对象
bean的作用域
在Spring中可设置创建的bean是单实例还是多实例
默认是单例的
验证:
通过设置bean标签的scope属性设置实例数量:
singleton:单例,每次从容器拿都是同一个
prototype:原型,每次从容器拿都是新的
request:一个request一个实例
session:一个session一个实例
global session
前两个属性值的细微区别:
前者在加载xml文件时就会创建单例对象
后者是在调用getBean()方法的时候才创建实例对象(每调一次会创建一个新的)
bean的生命周期
生命周期定义:创建->销毁
1.通过(无参)构造器创建bean实例
2.为bean的属性设置值和对其他bean的引用(调用setter方法)
3.调用bean的初始化方法
需在bean标签中设置init-method属性值为指定方法名
4.bean可以使用了
5.当容器关闭的时候,调用bean的销毁方法
需在bean标签中设置 destroy-method属性值为指定方法名,该方法中应包含context.close()方法
⚠️注意:如果加上了bean的后置处理器(实现BeanPostProcessor接口)
那么bean的生命周期应该有七步,在初始化(第3步)的前后会把bean的实例传给bean后置处理器的方法
AOP
面向切面编程,是一种编程思想
降低耦合度,提高可重用性
不通过修改源代码的方式,在主干功能中添加新的功能
动态代理
,多读读这篇文章,会有新的收获
jdk——需要接口
懵逼了可以去看看P27,=27&spm_id_from=pageDriver
说白了就是:现在有个接口,接口有个实现类,有一个我们自己定义的代理类(实现了InvocationHandler接口,重写了invoke方法),将接口实现类传到自定义的代理类中,让代理类去增强实现类中指定的方法。(要告诉代理类是哪个方法,使用了哪个实现类)
cglib——无需接口
AspectJ是一个aop框架,可通过注解和配置文件工作
当有接口,有目标类的时候,aspectJ使用的是jdk的动态代理,当只有目标类,没有接口,使用的是cglib动态代理。
术语
1.连接点:理论上可以被增强的方法
2.切入点:实际上真正被增强的方法
3.通知(增强):增强的内容
环绕通知 Around
前置通知 Before
最终通知 After
后置(返回)通知 AfterReturning
异常通知 AfterThrowing
执行顺序
无异常情况:Around->Before->自己的method->Around->After->AfterReturning
异常情况:Around->Before->自己的method->Around->After->AfterThrowing
可见后置和异常两者不能共存
4.切面(它是一个动作,把通知应用到切入点的过程)
切入点
抽取切入点,以便复用
其他
aop使用到了责任链模式
.html
为什么每次都要回到链上呢?
因为每次链上的元素会重新排序(chain的元素顺序是基于拓扑排序的),所以得回去获取到新排序后的对应通知对象
事务
Spring中有两种事务
编程式事务管理(不推荐)
声明式事务管理(底层是AOP)
可用注解(常用)或 xml 配置
Spring事务管理API——事务管理器
Spring事务传播行为
事务方法:能够改变数据库数据的操作
七种传播行为的前两种要记住
required
当前有事务?加入它;当前无事务?启动一个新的事务并加入
required_new
启动一个新的事务并加入,如果已经有旧的事务将它挂起
隔离级别
用于并发,隔离性(多事务间不产生影响)
脏读
一个未提交事务A读取到了另一个未提交事务B的数据,一旦事务B回滚,那么A持有的B的数据就成了脏数据。
不可重复读
一个未提交事务读取到了另一提交事务修改的数据
幻读/虚读
一个未提交的事务读取到了另一提交事务新添加的数据
通过设置事务的隔离级别,可以解决上述问题
可在@Transactional标签中设置isolation属性
待看:=search&seid=2975270978271107013
发布评论