Spring
<p>[TOC]</p>
<h1>13. Spring</h1>
<p><a href="https://blog.csdn.net/a745233700/article/details/80959716">spring常见面试题</a></p>
<h2>13.1. Spring 基础</h2>
<h3>13.1.1. 不同版本的Spring Framework有哪些主要功能</h3>
<p>Spring2.5:第一个支持注解的版本</p>
<p>Spring3:支持JavaEE6</p>
<p>Spring4:第一个完全支持Java8的版本</p>
<h3>13.1.2. 什么是Spring</h3>
<p>Spring是一个开源的应用框架,创建初衷是为了降低应用程序开发的复杂度,可以集成其他框架,所以也被称为框架的框架。</p>
<h3>13.1.3. Spring框架的优点</h3>
<p>1. 由于依赖注入和控制反转,简化了JDBC</p>
<p>2. 开源免费</p>
<h3>13.1.4. Spring有哪些功能</h3>
<p>1. 轻量级:Spring在代码量和透明度方面都很轻便</p>
<p>2. IOC:控制反转</p>
<p>3. AOP:面向切面编程,可以将应用业务逻辑和系统服务分离,实现高内聚</p>
<p>4. 容器:Spring负责创建和管理对象Bean的生命周期和配置</p>
<p>5. MVC:对web应用提供了高度可配置性,其他框架的集成也十分方便</p>
<p>6. 事务管理:提供了用于事务管理的通用抽象层</p>
<p>7. 异常处理:Spring的JDBC抽象层提供了一个异常层次结构,简化了错误处理策略</p>
<h3>13.1.5. Spring框架的模块</h3>
<p>1. 数据访问/集成模块,提供与数据库交互的支持</p>
<p>● JDBC</p>
<p>● ORM Object relational mapping 可以使用对象关系映射工具</p>
<p>● OXM Object xml mappers</p>
<p>● JMS java messaging service</p>
<p>● Transactions </p>
<p>2. Web模块,提供创建web应用程序的支持</p>
<p>● Web</p>
<p>● WebSocket</p>
<p>● WebServlet</p>
<p>● WebPortlet</p>
<p>3. AOP模块,支持面向切面编程</p>
<p>4. Instrumentation模块,提供类检测和类加载器实现</p>
<p>5. 核心容器模块,Spring框架核心</p>
<p>● Core</p>
<p>● Beans</p>
<p>● Context</p>
<p>● SpEL</p>
<p>6. Test模块,提供JUint TestNG测试</p>
<h3>13.1.6. Spring配置文件</h3>
<p>Spring配置文件是XML文件,该文件主要包含类信息,描述了这些类如何配置及相互引入的。</p>
<h3>13.1.7. Spring应用程序有哪些不同组件</h3>
<p>1. 接口:定义功能</p>
<p>2. Bean类:包含属性、set get方法、函数等</p>
<p>3. AOP:提供面向切面编程功能</p>
<p>4. Bean配置文件:包含类信息以及如何配置他们</p>
<p>5. 用户程序:使用接口</p>
<h3>13.1.8. 使用Spring的方式</h3>
<p>1. 作为一个Spring Web应用程序</p>
<p>2. 作第三方Web框架,使用Spring框架中间层</p>
<p>3. 用于远程使用</p>
<p>4. 作Java Bean 包装现有的POJO plain old java objects</p>
<h2>13.2. IOC</h2>
<h3>13.2.1. 什么是Spring IOC容器</h3>
<p>Spring IOC用于创建对象、管理对象、配置对象,管理对象的生命周期。</p>
<p>通过依赖注入来管理对象,通过读取配置元数据来实例化和配置对象,元数据可以通过XML、Java注解来提供。</p>
<h3>13.2.2. 什么是IoC</h3>
<p>IoC即控制反转,是一种设计思想,其核心是将对象的控制权由编码人员交由IOC容器去管理,屏蔽了对象创建和管理的过程,使得程序员可以专注于逻辑处理。</p>
<h3>13.2.3. 什么是依赖注入DI</h3>
<p>依赖注入指的是spring创建对象的过程中,把对象依赖的属性注入到对象中,以此降低对象间的耦合度。</p>
<h3>13.2.4. 依赖注入的方法</h3>
<p>1. 构造函数注入</p>
<p>有参构造函数</p>
<pre><code>public class SpringAction { //注入对象springDao private SpringDao springDao; private User user; public SpringAction(SpringDao springDao,User user){ this.springDao = springDao; this.user = user; System.out.println(&quot;构造方法调用springDao和user&quot;); } public void save(){ user.setName(&quot;卡卡&quot;); springDao.save(user); } }
</code></pre>
<p>1. set方法注入</p>
<p>定义成员变量,创建set方法</p>
<pre><code>package com.bless.springdemo.action; public class SpringAction { //注入对象springDao private SpringDao springDao; //一定要写被注入对象的set方法 public void setSpringDao(SpringDao springDao) { this.springDao = springDao; } public void ok(){ springDao.ok(); } }
</code></pre>
<p>1. 静态工厂注入</p>
<p>调用静态工厂的方法获取对象</p>
<pre><code>//静态工厂package com.bless.springdemo.factory; import com.bless.springdemo.dao.FactoryDao; import com.bless.springdemo.dao.impl.FactoryDaoImpl; import com.bless.springdemo.dao.impl.StaticFacotryDaoImpl; public class DaoFactory { //静态工厂 public static final FactoryDao getStaticFactoryDaoImpl(){ return new StaticFacotryDaoImpl(); } }//类public class SpringAction { //注入对象 private FactoryDao staticFactoryDao; public void staticFactoryOk(){ staticFactoryDao.saveFactory(); } //注入对象的set方法 public void setStaticFactoryDao(FactoryDao staticFactoryDao) { this.staticFactoryDao = staticFactoryDao; } }
</code></pre>
<p>1. 实例工厂注入</p>
<p>先获取工厂类实例对象再调用其方法</p>
<pre><code>//实例工厂public class DaoFactory { //实例工厂 public FactoryDao getFactoryDaoImpl(){ return new FactoryDaoImpl(); } }//调用类public class SpringAction { //注入对象 private FactoryDao factoryDao; public void factoryOk(){ factoryDao.saveFactory(); } public void setFactoryDao(FactoryDao factoryDao) { this.factoryDao = factoryDao; } }
</code></pre>
<p>构造函数注入和set注入的区别</p>
<p>1. 构造函数注入没有部分注入,set注入有部分注入</p>
<p>2. 构造函数注入不会覆盖set属性,set注入会覆盖set属性</p>
<p>3. 构造函数注入任意修改都会创建一个新实例,set注入任意修改不会创建新实例</p>
<p>4. 构造函数注入适用于设置很多属性,set注入适用于设置少量属性</p>
<p>静态工厂注入和实例工厂注入的区别</p>
<p>1. 静态工厂注入创建的对象的值和地址是一致的,实例工厂注入创建的对象地址不一样</p>
<p>2. 静态工厂注入的时候调用的是静态方法,实例工厂注入调用的是普通方法</p>
<h3>13.2.5. IOC容器 BeanFactory ApplicationContext</h3>
<p>1. BeanFactory,类似于一个包含bean集合的工厂类</p>
<p>2. ApplicationContext,它拓展了BeanFactory接口</p>
<p>BeanFactory和ApplicationContext的区别</p>
<p>1. BeanFactory使用懒加载,即只有在使用到某个Bean时才对该Bean进行实例化,不利于错误的检查;ApplicationContext使用即时加载,是在容器启动的时候,一次性创建所有Bean,方便配置问题的检查,但因此ApplicationContext会占用内存空间,若Bean配置较多时,程序启动较慢。</p>
<p>2. BeanFactory不支持国际化,ApplicationContext支持国际化</p>
<p>3. BeanFactory使用语法显示提供资源对象,ApplicationContext自己创建和管理资源对象</p>
<p>4. BeanFactory不支持基于依赖的注解,ApplicationContext支持基于依赖的注解</p>
<h3>13.2.6. IoC的好处</h3>
<p>由容器实现依赖对象的注入,并不需要指定具体的依赖,降低了程序的耦合度,依赖对象更新的时候只需要注入新的实例即可,不需要作更繁琐的修改,便于程序维护。</p>
<h3>13.2.7. IOC容器的好处</h3>
<p>可以自动实现对象的依赖注入,创建实例的时候不需要了解具体细节,程序员只需要维护好配置文件即可,不需要手动控制依赖对象的获取。</p>
<h3>13.2.8. IoC的实现机制</h3>
<p>1. 解析配置文件,获取对象信息</p>
<p>2. 根据解析后的关系实例化对象</p>
<p>3. 注入依赖</p>
<h2>13.3. AOP</h2>
<h3>13.3.1. 什么是AOP</h3>
<p>AOP即面向切面编程,不同于OOP面向对象编程,OOP构建程序的基础是类,AOP的基础是切面Aspect。</p>
<h3>13.3.2. 什么是切面Aspect</h3>
<p>面向对象编程时,程序可以方便的作纵向延申,但是不便于作横向延申,因为这样会造成大量代码重复。</p>
<p>面向切面编程作为面向对象编程的一个补充,将那些与业务无关但是涉及到很多对象的公共逻辑抽取出来形成一个可重用的模块,这个模块就称为切面。切面由切点pointcut和通知advice组成。</p>
<h3>13.3.3. 什么是连接点JoinPoint</h3>
<p>是一个位置,指程序执行过程中的某个特定的点,比如方法调用前、方法调用后等。</p>
<h3>13.3.4. 什么是切点 PointCut</h3>
<p>切点定义了需要对哪些连接点进行拦截。</p>
<h3>13.3.5. 什么是通知Advice</h3>
<p>指在连接点上执行的程序,是一段增强的逻辑,比如日志打印等。</p>
<p>通知类型:</p>
<p>● Around 环绕通知:包围连接点的通知,可以在方法执行前后完成自定义的行为</p>
<p>● Before 前置通知:在连接点前执行</p>
<p>● After 后置通知:在连接点退出时执行,不论正常返回还是异常返回</p>
<p>● AfterReturning 返回后通知:在连接点正常完成后执行</p>
<p>● AfterThrowing 异常通知:在方法抛出异常时执行</p>
<h3>13.3.6. 什么是目标对象Target</h3>
<p>目标对象即包含了连接点的对象,就是增强的逻辑应插入的目标类。</p>
<h3>13.3.7. 什么是织入 Weaving</h3>
<p>把增强的逻辑添加到目标位置的过程。</p>
<h3>13.3.8. 什么是代理 Proxy</h3>
<p>是对目标对象进行增强后形成的对象就是代理对象。</p>
<h3>13.3.9. AOP的实现方式</h3>
<p>1. 静态代理,指使用AOP框架提供的命令进行编译,在编译的时候生成AOP代理类,因此也称之为编译时增强。</p>
<p>2. 动态代理,指在运行时在内存中临时生成AOP动态代理类,因此也称之为运行时增强。</p>
<h2>13.4. Beans</h2>
<h3>13.4.1. 什么是Bean</h3>
<p>Bean是由IOC容器根据元数据创建、配置、管理的对象。</p>
<h3>13.4.2. Spring的配置方式</h3>
<p>1. 基于XML配置,把bean所需要的依赖项等配置在XML文件中。</p>
<p>2. 基于注解配置,通过为类、方法、字段等声明注解来配置,把bean配置为组件类。</p>
<p>3. 基于Java API配置,通过@Bean、@Configuration来实现</p>
<h3>13.4.3. Bean的生命周期</h3>
<p>大致分为四个阶段:</p>
<p>1. 实例化,读取配置文件中的信息进行bean的实例化</p>
<p>2. 属性赋值,容器为实例化的Bean设置属性值,检查是否实现了aware接口</p>
<p>3. 初始化,检查是否定义了初始化方法</p>
<p>4. 销毁,容器销毁bean时,检查是否定义了销毁方法</p>
<h3>13.4.4. spring的内部bean</h3>
<p>把bean作用于另一个bean的属性的时候,此时生命的bean即内部bean,它总是匿名的。</p>
<h3>13.4.5. 什么是spring装配</h3>
<p>容器将bean组合在一起的时候,就称为装配。</p>
<h3>13.4.6. 自动装配的方式</h3>
<p>1. no,默认设置,表示没有自动装配</p>
<p>2. byName,根据bean名称注入对象依赖</p>
<p>3. byType,根据类型注入对象依赖</p>
<p>4. 构造函数,调用类的构造函数来注入依赖</p>
<p>5. 自动检测,首先尝试根据构造函数使用autowaire装配,行不通就根据byType装配</p>
<h3>13.4.7. 自动配置的局限性</h3>
<p>1. 自动装配总会被手动装配覆盖</p>
<p>2. 自动装配无法匹配基本数据类型</p>
<h2>13.5. 注解</h2>
<h3>13.5.1. 基于注解的容器配置</h3>
<p>不通过XML,而是通过在相关的类、方法、字段上声明注解来配置。默认情况下没有开启注解装配,需要通过配置启用。</p>
<h3>13.5.2. @Component @Controller @Repository @Service有何区别</h3>
<p>@Component将Java类标记为bean</p>
<p>@Controller将类标记为Spring Web MVC控制器</p>
<p>@Repository类似于@Component,将DAO引入IOC容器</p>
<p>@Service是在服务层使用的注解</p>
<h3>13.5.3. @Required注解的作用</h3>
<p>@Required定义在bean的set方法上,标明此属性在装配时必须填充。</p>
<h3>13.5.4. @Autowired注解的作用</h3>
<p>@Autowired可用于set方法、构造函数,它可以更准确的控制在什么地方如何进行自动装配</p>
<h3>13.5.5. @RequestMapping注解的作用</h3>
<p>@RequestMapping用于将特定的http请求映射到将处理相应请求的控制器中的特定类/方法</p>
<h2>13.6. 数据访问</h2>
<h3>13.6.1. DAO有什么作用</h3>
<p>将数据访问的任务统一到一起,将常用的操作封装起来,提高了代码的重用性。</p>
<h2>13.7. 事务管理</h2>
<h3>13.7.1. spring事务管理类型</h3>
<p>1. 编程式事务管理:需要通过编程的方式管理事务,但是这种方式比较难维护。</p>
<p>2. 声明式事务管理:可以将业务代码和事务管理分离,只需要用注解和XML配置来管理事务。</p>
<h3>13.7.2. spring事务管理的特点</h3>
<p>1. 原子性:事务是一个不可分割的整体,要么事务全部发生,要么全部不发生</p>
<p>2. 一致性:事务前后的数据完整性必须保持一致</p>
<p>3. 隔离性:多个事务并发,互不干扰,相互之间有数据隔离</p>
<p>4. 持久性:事务发生后,造成的改变是永久的</p>