Spring知识点
- Spring是什么?
- Spring 是一个轻量级的IOC(Inversion of Control)和AOP(Aspect Oriented Programming)容器的框架。主要就是为了解决企业应用的开发,使开发者只需关注业务逻辑即可。
- Spring配置方式:XML配置、注解配置和Java配置【https://blog.csdn.net/qq_21508727/article/details/80773252】
- Spring由以下模块组成:
- Spring core:Spring的核心类库,提供IOC服务
- Spring Context:提供框架式的Bean的访问方式
- Spring AOP:提供AOP服务
- Spring Dao:Data Access Object(数据访问对象) 提供对JDBC(Java DataBase Connectivity)的抽象
- Spring ORM:Object Relational Mapping(对象关系映射) 对现有的绝大部分的ORM框架的支持
- Spring Web:提供针对Web开发的继承特性,如:文件上传
- Spring MVC:提供面向Web应用的Model-view-Controller的实现
- 为什么使用Spring?
- Spring提供IOC服务,容器能够帮助管理依赖对象,从而不需要自己创建和管理对象,更轻松的实现了程序的解耦
- Spring提供了对事务的支持,使事务操作更方便
- Spring提供了AOP服务,使解决问题更加方便
- Spring支持多种框架的集成,如:MyBatis、Hibernate等
- OOP与AOP的区别是什么?
- OOP:Object Oriented Programming(面向对象编程),针对业务处理过程中的实体以及属性和方法进行抽象和封装,以获得清晰及高效的逻辑单元划分
- AOP:Aspect Oriented Programming(面向切面编程),针对业务处理过程中的切面进行提取,提取的是处理过程中的某个步骤和阶段,以获得业务逻辑各部分的低耦合隔离的效果
- 讲讲对Spring的AOP理解?
- Aspect Oriented Programming(面向切面编程),通过预编译和运行时的动态代理来完成程序中的功能。简单来说就是统一处理一个“切面”(类)的问题的编程思想,如:统一处理日志和异常
- AOP中的概念定义:
- JoinPoint(连接点):控制的每一个方法
- PointCut(切入点):控制规则的定义
- Advice(通知):
- 前置通知(Before Advice 前置增强):在一个JoinPoint的之前执行的通知,即:在执行before()方法之前的通知
- 后置通知(AfterReturnning Advice 后置增强):当一个JoinPoint的成功执行完之后执行的通知,即:在afterReturn()正常执行完之后的通知
- 异常抛出通知(After Throwing Advice):当一个方法中抛出异常时执行的通知
- 最终通知(After(finally) Advice):不管有没有正常执行完毕都执行的通知
- 环绕通知(Around Advice):围绕一个JoinPoint的通知,由Before Advice和AfterReturn Advice组成的,Nanning和JBoss4只提供环绕通知
- Aspect(切面):由PointCut和Adivce组成,两者决定了切面的定义,通过@Aspect注解实现
- Target(目标对象):程序运行期生成目标对象的代理对象
- Weave(织入):程序运行期生成目标对象的代理对象的过程
- Introduction(引入):程序运行期为类动态的添加方法或属性的过程
- Aspect Oriented Programming(面向切面编程),通过预编译和运行时的动态代理来完成程序中的功能。简单来说就是统一处理一个“切面”(类)的问题的编程思想,如:统一处理日志和异常
- 讲讲对Spring的IOC的理解?
- Inversion of Control(控制反转),简单来说,我们就是把new操作交给Spring IOC的容器,通过Java的反射机制,在程序运行时根据配置文件动态的创建和管理对象,以及调用对象的方法
- DI(Dependency Injection)依赖注入,和控制反转是同一概念而不同的描述,在程序运行时通过IOC容器动态注入对象需要的外部资源
- IOC的注入方式:构造器注入、setter注入、注解注入
- Inversion of Control(控制反转),简单来说,我们就是把new操作交给Spring IOC的容器,通过Java的反射机制,在程序运行时根据配置文件动态的创建和管理对象,以及调用对象的方法
- Spring的Bean的生命周期?
- 在使用未被初始化的Bean时,Bean的生命周期:【https://blog.csdn.net/Longmanfei/article/details/83906723】
- BeanFactory容器寻找Bean配置文件并实例化Bean
- 依赖注入,Spring根据Bean的配置文件来完成Bean的所有依赖的注入
- 如果Bean实现了BeanNameAware接口,就会执行setBeanName()传递Bean的ID
- 如果Bean实现了BeanFactoryAware接口,就会执行setBeanFactory()传入工厂本身
- 如果Bean实现了BeanPostProcessor接口,就会在初始化之前执行postProcessorBeforeInitialization()进行预处理操作
- Bean的初始化:
- 如果Bean实现了InitializingBean接口,就会执行afterPropertiesSet()方法进行初始化
- 如果配置文件中配置了init-method,执行配置中的初始化方法
- 最后,如果Bean实现了BeanPostProcessor接口,就会执行PostProcessorAfterInitialization()进行初始化的处理,执行完代表Bean创建完成。
- Bean的销毁:
- 如果Bean实现了DisposableBean接口,那么我们可以调用destory()进行销毁Bean
- 如果Bean的配置文件中配置了destory-method,则会自动调用配置文件中的销毁方法
- 在使用未被初始化的Bean时,Bean的生命周期:【https://blog.csdn.net/Longmanfei/article/details/83906723】
- Spring的Bean的作用域有哪几种?Spring的Bean是线程安全的吗?
- 5种作用域:
- singleton:默认作用域,SpringIOC只提供一个Bean的实例,即每次返回的都是同一个Bean实例
- prototype:SpringIOC为每一个Bean创建一个新实例,即每次返回的都是一个新的实例
- Web环境下的作用域:
- request:每一次http请求都会创建一个新的实例
- session:在一个http session会话中共享一个实例
- global-session:用于portlet容器中,每一个portlet容器都拥有独自的session,global-session提供了全局性的http session
- 一般情况下,在无状态或状态不可变的类中适合使用单例模式。在传统的开发中,Dao类拥有Connection这个线程不安全的对象因而没有单例模式;在Spring中,所有Dao类都能使用单例模式,因为Spring使用AOP和Java API中的ThreadLocal对象对线程不安全的对象做了特殊的处理。Spring的Bean作用域默认模式是“singleton”,而Spring并没有对Bean的单例模式下进行多线程的封装。绝大部分情况Spring Bean是无状态【指的是不会存储数据】的(如:DAO类),那么在某种程度上来说是线程安全的,但如果Spring Bean是有状态【指的是会存储数据】的(如:view、model对象),线程安全就需要开发者维护,最简单的方式就是修改作用域,将“singleton”改为“prototype”
- ThreadLocal顾名思义本地线程对象,在多线程应用中线程使用ThreadLocal去维护变量时,其会为使用此变量的所有线程创建线程副本,所有线程都可以独立的对自己的线程副本进行修改并且不会影响其他线程的副本。从线程的角度来看,线程副本就像线程的本地变量
- ThreadLocal是如何维护独立的线程副本的?ThreadLocal中有一个Map,键是线程对象,值则是线程对应变量的副本
- 5种作用域:
- Spring基于XML注入Bean的方式有几种?
- set方法的注入
- 构造器的注入
- 静态工厂的注入
- 实例工厂的注入
- set方法的注入
- Spring自动装配Bean有哪些方式?
- 基于XML:
- no:默认装配方式,设置ref属性来进行装配Bean
- byName:通过设置name属性进行装配,如果一个Bean中的property的值与另一个Bean中的name值相同,那么就会自动装配
- byTpye:通过参数的数据类型进行装配
- constructor:通过构造器进行装配,并且构造器参数是使用byType进行装配
- autodetect:容器首先通过构造器使用autowire进行装配,如果不能,则使用byType自动装配
- 使用注解:
- @Autowired:通过byType(符合Spring规范)进行装配的,要求依赖的对象必须存在,如果要允许为null,那么可以将require属性设置为false(@Autowired(require=false)),如果先要通过name进行装配可以配合@Qualifier注解进行使用
- @Resource:通过byName(符合J2EE规范)进行装配的,如果name属性没有指定,当注解放在字段上,默认用字段名进行名称查找,当放在setter方法上默认使用属性名进行装配。如果没有查询到则使用byType进行装配。需要我们注意的是如果name属性被指定了,那么只能使用byName进行装配
- @Autowired:通过byType(符合Spring规范)进行装配的,要求依赖的对象必须存在,如果要允许为null,那么可以将require属性设置为false(@Autowired(require=false)),如果先要通过name进行装配可以配合@Qualifier注解进行使用
- 基于XML:
- Spring框架中使用到的设计模式有哪些?
- 工厂模式:BeanFactory就是工厂模式的体现,用来创建实例Bean对象
- 模板模式:用来解决代码重复的问题
- 代理模式:Spring AOP就使用了JDK动态代理和CGLIB动态代理
- 单例模式:Spring Bean默认是单例模式
- 观察者模式:是对象键的一种一对多的依赖关系,当一个对象状态被修改时,依赖的其他对象就会得到通知被制动更新
- 工厂模式:BeanFactory就是工厂模式的体现,用来创建实例Bean对象
- Spring事务实现方式有哪些?
- 编程式事务管理:
- 通过提供编码的形式进行管理和维护事务
- 优点:最细粒度能够作用到代码块
- 缺点:对代码的侵入
- 优点:最细粒度能够作用到代码块
- 通过提供编码的形式进行管理和维护事务
- 声明式事务管理:
- 基于AOP功能完成,对方法前后进行拦截,将事务处理的操作编写到拦截方法中,当目标方法执行完根据执行情况进行提交或回滚事务
- 优点:对代码无侵入性,可以使用@Transaction注解完成对事务的控制
- 缺点:最细粒度只能够作用到方法
- 基于AOP功能完成,对方法前后进行拦截,将事务处理的操作编写到拦截方法中,当目标方法执行完根据执行情况进行提交或回滚事务
- 编程式事务管理:
- 说一下Spring的事务隔离?
- Spring的事务隔离的本质就是数据库对事务的支持,如果数据库没有对事务的支持,Spring的也就无法提供事务的功能
- 事务的四种特性:
- 原子性:保证事务不可分割
- 一致性:事务执行之后的数据完整性必须一致
- 隔离性:事务执行过程中不能够被其他事务所干预
- 持久性:事务执行结束后会持久化到数据库中
- 事务的五种隔离级别:
- ISOLATION_DEFAULT:Spring使用底层数据的事务隔离级别
- ISOLATION_READ_UNCOMMITTED:读未提交,最低的隔离级别,事务未提交数据就能被其他事务读取,会出现脏读、幻读和不可重复读的问题
- ISOLATION_READ_COMMITTED:读已提交,事务已提交数据其他事务才能进行读取,会出现幻读和不可重复读的问题,SQLServer的默认级别
- ISOLATION_REPEATABLE_READ:可重复读,保证事务多次读取同一数据时,其值必须和事务开始时的内容相同,会出现幻读的问题,MySQL的默认级别
- ISOLATION_SERIALIZABLE:序列化,最高的隔离级别,能够防止脏读、幻读和不可重复读的问题
- 三种在事务中常见的安全问题:
- 脏读:当一个事务还未提交数据就被其他事务读取
- 幻读:同一个事务多次查询到的结果集都不相同。幻读产生的原因是因为其他事务修改了(Insert和delete操作)此事务中数据所导致查询出的结果多了或少了数据
- 不可重复读:在一个事务内,多次访问一个数据,得到的数据不相同(update操作)
- Spring的事务隔离的本质就是数据库对事务的支持,如果数据库没有对事务的支持,Spring的也就无法提供事务的功能