Spring框架面试题总结(面试必备)

写在前面:继续看看spring的面试题,打开ThinkWon大神的总结,不禁吸了两口真气,由于是初学者,很多知识点没有学到,这边只记录学到的,并且能理解的,部分加入自己的想法,一些不能理解的问题应该深入学习后再来补充。
原文链接:https://blog.csdn.net/ThinkWon/article/details/104397516

目录

1. spring 概述部分

1.1 什么是spring?

spring是一个轻量级的JavaEE开源框架,开发spring的根本使命目的是为了企业应用开发的复杂性,即简化Java开发。
spring的两个核心特性:控制反转和面向切面编程,即IOC和AOP。
spring 的特点:

  1. 轻量:从大小和开销方面而言spring都是轻量的,处理开销也是微不足道的。
  2. <mark>IOC</mark>:削减计算机之间的耦合,降低程序代码中的依赖关系。
  3. <mark>AOP</mark>:通过配置管理特性spring的AOP,可以将一些通用的任务,如安全,事务,日志等集中进行管理,提高了程序的复用性和管理型。
  4. 容器:Spring提供了容器功能,容器可以管理对象的生命周期、对象与对象间的关系、我们可以通过编写XML来设置对象关系和初始值,这样容器在启动之后,所有的对象都直接可以使用,不用编写任何编码来产生对象。Spring有两种不同的容器:Bean工厂以及应用上下文。
  5. 框架:可以将简单的组件配置,组成复杂的应用,spring也提供了很多基础功能(事务管理,持久化框架集成)将应用逻辑留给开发者。

1.2 spring框架的核心?

IOC和AOP模块。通过IOC容器管理POJO或JavaBean对象,以及它们之间的耦合关系;通过AOP以动态非入侵的方式增强服务。

1.3 spring框架的优缺点

<mark>优点</mark>

  1. 方便解耦,简化开发

Spring就是一个大工厂,可以将所有对象的创建和依赖关系的维护(DI),交给Spring管理。

  1. AOP编程的支持

Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控和增强等功能。

  1. 声明式事务的支持

只需要通过配置就可以完成对事务的管理,而无需手动编程。

  1. 方便程序的测试

Spring对Junit4支持,可以通过注解方便的测试Spring程序。

  1. 方便集成各种优秀框架

Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架的直接支持(如:Struts、Hibernate、MyBatis等)。

  1. 降低JavaEE API的使用难度

Spring对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低。

<mark>缺点</mark>

  1. Spring明明一个很轻量级的框架,却给人感觉大而全,内容太庞大。
  2. Spring依赖反射,反射影响性能
  3. 使用门槛升高,入门Spring需要较长时间

1.4 spring5 的主要模块构成

Spring 总共大约有 20 个模块, 由 1300 多个不同的文件构成。 而这些组件被分别整合在<mark>核心容器(Core Container) 、 AOP(Aspect Oriented Programming)和设备支持(Instrmentation) 、数据访问与集成(Data Access/Integeration) 、 Web、 消息(Messaging) 、 Test</mark>等 6 个模块中。 以下是 Spring 5 的模块结构图

  • spring core:提供了框架的基本组成部分,包括控制反转(Inversion of Control,IOC)和依赖注入(Dependency Injection,DI)功能。
  • spring beans:提供了BeanFactory,是工厂模式的一个经典实现,Spring将管理对象称为Bean。
  • spring context:构建于 core 封装包基础上的 context 封装包,提供了一种框架式的对象访问方法。
  • spring jdbc:提供了一个JDBC的抽象层,消除了烦琐的JDBC编码和数据库厂商特有的错误代码解析, 用于简化JDBC。
  • spring aop:提供了面向切面的编程实现,让你可以自定义拦截器、切点等。
  • spring Web:提供了针对 Web 开发的集成特性,例如文件上传,利用 servlet listeners – 进行 ioc 容器初始化和针对 Web 的 ApplicationContext。
  • spring test:主要为测试提供支持的,支持使用JUnit或TestNG对Spring组件进行单元测试和集成测试。

1.5 Spring 框架中都用到了哪些设计模式?

  1. 工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;
  2. 单例模式:Bean默认为单例模式。
  3. 代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;
  4. 模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。

1.6 讲解一下核心容器(spring context应用上下文) 模块

应用上下文模块是spring框架的基本模块,BeanFactory是任何以spring为基础的应用的核心,spring框架建立在context这个模块上,使得spring成为一个容器。
Bean工厂是工厂模式的一个实现,提供了控制反转的功能。用来把应用的配置和依赖真正从代码中分离出来。最常用的是根据xml文件加载bean对象进IOC容器中,使得的类是ApplicationContext的实现类org.springframework.beans.factory.xml.XmlBeanFactory。

2. spring的控制反转(IOC)

2.1 什么是Spring IOC 容器?

所谓控制反转主要是把传统上的程序直接向内存中申请空间创建对象的这个控制权转移到了外部工厂,通过工厂来对这些创建好的对象进行装配和管理。外部工厂即我们常说的IOC容器,spring IOC负责创建对象,管理对象(依赖注入,装配对象Autowride)并管理这些对象的整个生命周期。

2.2 IOC 有什么作用?

  1. 管理对象的创建和依赖关系的维护。
  2. 解耦降低了依赖,由容器去维护具体的对象的创建。
  3. bean对象生命周期管理。

2.3 使用IOC容器的优点?

  1. IOC和DI的配合使用能把应用的实际代码量降到最低。
  2. spring集成了自己的测试模块,无需依赖于junit。
  3. IOC容器支持立即加载和延迟加载(懒加载)。

2.4 spring IOC支持哪些功能

  1. 依赖注入
  2. 依赖检查
  3. 自动装配
  4. 支持集合

2.5 BeanFactory 和 ApplicationContext有什么区别?

BeanFactory 和 ApplicationContext都是spring的两个核心的接口,都可以当作容器来使用,其中BeanFactory是ApplicationContext父接口。它们之间的区别由:
依赖关系:BeanFactory是spring中最底层的接口,包含了各种bean的定义,读取bean的配置文档,管理bean的加载,实例化,控制bean生命周期,维护bean之间的依赖关系。
而ApplicationContext作为BeanFactory 的子接口,除了BeanFactory本身的功能外,提供了更加完善的框架功能。如:

  1. 继承MessageSource,因此支持国际化。
  2. 统一资源文件的访问方式
  3. 同时加载多个配置文件
  4. 提供***中注册bean的事件

加载方式:BeanFactory采用的是延迟加载的方式,即当我们要使用bean时调用getBean方法开始实例化bean对象。如此我们容易遇到就是在配置文件中忘记配置bean(未注入),而去调用它的getBean对象,将会抛出异常。
ApplicationContext是在容器启动后,创建所有的bean,比起BeanFactory的加载方式,采用ApplicationContext的加载更容易发现spring配置中的问题,有利于检查依赖是否注入,加载出来的单例bean对象,可以直接拿去用而不用等待。
创建方式:BeanFactory通常以编程的形式被创建,而ApplicationContext还能以声明的形式被创建,如ContextLoader.

2.6 ApplicationContext通常的实现是什么?

  1. ClassPathXmlApplicationContext:此容器从xml中加载beans的定义,将在classpath中寻找bean的定义。
  2. FileSystemXmlApplication:和ClassPathXmlApplicationContext类似从xml中加载beans的定义,但是范围可以时硬盘上的任意位置,只要有访问权限。
  3. AnnotationConfigApplicationContext:用于读取注解创建容器。

2.8 什么是Spring的依赖注入?

依赖关系的维护又称为依赖注入,这种关系交给spring来管理,当我们在类中要用到其它的类对象,都由spring来提供,我们只需要在配置文件中说明即可,依赖注入也是IOC控制反转的一种实现。

2.9 依赖注入有什么优势?

依赖注入之所以流行,是因为它是一种很可取的方式:让r容器全权负责依赖的查询,需要注入的bean对象只需要暴露出JavaBean的setter方法或者带参数的构造函数,使得容器在初始化时组装对象依赖关系。与其依赖查找方式相比,主要的优势有:

  1. 查找定位操作与应用代码无关
  2. 不依赖于容器的API,可以很容易地在任何容器以外使用应用对象。
  3. 不需要特殊的接口,绝大多数对象可以做到完全不必依赖容器。

2.10 有哪些不同类型的依赖注入实现方式?

依赖注入是时下最流行的IOC控制反转的一种实现,实现方式有接口注入,构造器注入,setter方法注入。其中由于接口注入的灵活性太差,于是与spring4被废弃。
构造器依赖注入:构造器依赖注入通过容器触发一个类的构造器来实现的,该类有一系列参数,每个参数代表一个对其他类的依赖。
Setter方法注入:Setter方法注入是容器通过调用无参构造器或无参static工厂 方法实例化bean之后,调用该bean的setter方法,即实现了基于setter的依赖注入。

2.11 构造器依赖注入和Setter方法注入的区别

构造器依赖注入 Setter方法注入
没有部分注入 有部分注入(提供setter)
不会覆盖setter属性 会覆盖setter属性
任意修改都会创建新的实例 任意修改都不会创建新的实例
适用于设置很多属性 适用于设置少量属性

3. spring 的 Bean

3.1 什么是Spring bean?

spring Bean是收到spring管理的bean对象,具体来说是被spring容器初始化,配置和管理的对象。spring Bean是再spring配置文件中定义的,现在也可以通过注解来定义,在spring容器初始化,注入到spring应用程序中。

3.2 一个 Spring Bean 定义 包含什么?

一个spring Bean的定义包含容器所必知道的配置元数据,包括如何创建一个bean,它的生命周期和它的依赖。

3.3 如何给Spring 容器提供配置元数据?Spring有几种配置方式

有三种配置方式

  1. 基于XML
  2. 基于注解配置
  3. 基于Java配置

前面两个比较常用。

3.4 Spring基于xml注入bean的几种方式

  1. setter方法注入
  2. 构造函数注入 ,配置index 参数位置和type参数类型
  3. 静态工厂注入
  4. 实例工厂

3.5 你怎样定义类的作用域?

如果是基于XML配置可以在bean标签内配置scope
如果spring需要bean的时候每次创建一个新的bean实例,这个时候应该使用多例,即scope = “prototype”。而如果使用一个bean对象,每次返回的是同一个bean对象,则scope = “singleton”。
基于注解开发同样有scope属性支持配置。

3.6 解释Spring支持的几种bean的作用域?

spring的bean的作用范围有5个:

  1. singleton:默认单例,每个容器中只能有一个bean的实例,单例模式由BeanFactory自身来维护。
  2. prototype:多例,为每一个bean创建一个实例,容器中可以存在多个实例。
  3. request:为每一个网络请求建立一个实例,当请求完成后,bean随之被GC回收。
  4. session:于request类似,每一个session会话有一个bean实例,当会话结束,bean随之失效。
  5. global-session:全局的session,通常用于集群服务器使用,用于建立集群服务器的会话,多台服务器可以共享session域,当只有一台时,建立的就是session会话。

注意: 缺省的Spring bean 的作用域是Singleton。使用 prototype 作用域需要慎重的思考,因为频繁创建和销毁 bean 会带来很大的性能开销。

3.7 Spring框架中的单例bean是线程安全的吗?

<mark>不是线程安全的。</mark>
spring框架并没有对单例bean进行任何的多线程封装处理。关于单例模式下的线程安全和并发问题需要程序员自己来解决,但是对于service和dao层,通常并不需要多个实例,即没有可变状态,所以默认情况下时我们说单例时线程安全的。如果你的bean有可变状态,如Model View对象,就需要自行保证线程的安全,最直接的方法就是修改bean的作用域scope从singleton改为prototype。

  • 有状态就是有数据存储功能
  • 无状态就是不会保存数据

3.8 Spring如何处理多线程并发问题?

多线程并发问题的根本在于相同的变量访问冲突问题。
通常,只有无状态的bean才可以再多线程***享,因为它们不会导致访问的冲突情况,spring中可以将绝大部分的bean对象声明为singleton。
但是还有一些有状态的bean为什么可以在多线程***享,如(RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等),因为它们采用了ThreadLocal进行处理,让它们也成为线程安全的状态,所以有状态的bean就可以在多线程***享了。
ThreadLocal 和 线程同步机制都是为了解决相同的变量访问冲突问题。
线程同步机制中的处理是通过加入对象锁处理,而ThreadLocal会为每个线程提供一个独立的变量副本,从而隔离了多线程数据的冲突访问,因为每个变量都有了自己的副本了,也就没必要对该变量进行数据同步了。ThreadLocal提供线程安全的共享对象,编写代码时,可以把哪些不安全的变量封装进ThreadLocal。

<mark>概括来说:</mark>
同步机制提供的是一种时间换空间的机制,多个线程只提供一个变量,让不同线程进行排队,避免了冲突的发生。
ThreadLocal采用的是一种空间换时间的方式,为每个线程都提供一个变量,因此可以同时访问而互不影响。

3.9 使用@Autowired注解自动装配的过程是怎样的?

使用@Autowired自动装配指定bean之前,需要在spring配置文件中进行以下配置。

<context:annotation-config/>

当启动spring的IOC容器后,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowired,@Resources,@Inject时,就会在IOC容器中查询需要的bean,并装配给该对象的属性。在使用@Autowired会在容器中寻找对应类型的bean:
由于容器类似一个一个Map结构,存储着key-value,查询机制是先从value上面找

  • 如果找到一个,则就将bean装配给@Autowired指定的数据
  • 如果找到两个,那么就从key值上面再找,找到则装配
  • 如果查询结果为空,则会抛出异常。解决方法,可以设置@Autowired的required的属性为false.

3.10 你可以在Spring中注入一个null 和一个空字符串吗?

可以的。

4. spring的常用注解

4.1 什么是基于Java的Spring注解配置? 给一些注解的例子

spring注解配置可以替换XML的配置,可以大大减少XML配置的代码量。
@Configuration:表示这是一个配置类,可以用来为IOC容器注入bean
@Bean:一般使用在配置类中,用于方法上面,将方法的返回值注入到IOC容器中,默认属性id为方法名。

4.2 怎样开启注解装配?

注解装配默认情况下是不开启的,如若开启,spring的XML文件中配置:

<context:annnotation-config/>

4.3 @Component, @Controller, @Repository, @Service 有何区别?

@Component:在类上加载此注解,可以将Java类标记bean,由spring来管理它。spring的组件扫描机制可以可以将其拾取并注入到应用程序环境中(IOC容器)。
@Controller,@Repository,@Service服务于web三层架构,分别是springMVC层,持久层,业务层,功能和@Component一样,为什么有这三个注解,因为它们更好的指明了使用意图。

4.4 @Required 注解有什么作用

@Required是为了保证对应的属性必须设置,@Required注释用于bean属性的setter方法,被它修饰的setter方法对应的属性必须在XML文件中注入,否则会抛出BeanInitializationException

示例:https://www.cnblogs.com/Guhongying/p/10598732.html

4.5 @Autowired 注解有什么作用

@Autowired是默认按照类型注入的,默认情况下它要求依赖必须存在,当然可以设置属性required为false,它的用法和required类似,可以作用域,属性,方法构造器或具有任意名称或任意参数的方法。

4.6 @Autowired和@Resource之间的区别

@Autowired:是默认按照类型注入的,默认情况下它要求依赖必须存在,当然可以设置属性required为false。
@Resource:默认是按照名称注入的,如果找不到名称匹配的bean,才会按照类型注入。

4.7 @Qualifier 注解有什么作用

用于指定bean名称的注解,和@Autowired配合使用,避免@Autowired因为找不到类型匹配的bean而抛出异常;或者找到多个bean用名称来消除歧义匹配唯一bean。

4.8 @RequestMapping 注解有什么用?

@RequestMapping用于接收HTTP请求,并将请求发送到相应的控制器类/方法上。作用位置有:

  • 类:映射请求的URL父级目录
  • 方法:映射URL和HTTP请求方法

5. spring的数据访问

5.1 JdbcTemplate是什么

JdbcTemplate是一个封装了JDBC规范的工具类,并且提供了很多遍历的方法,如执行写好或者可调用的SQL语句,提供把数据库的数据封装成基本数据类型或对象,提供自定义的数据错误处理。

5.2 Spring支持的事务管理类型, spring 事务实现方式有哪些?

spring支持两种事务的管理方案:
**编程式事务管理:**这意味着通过编程的方式管理事务,给你带来极大的灵活性,但是难以维护。
**声明式事务管理:**可以将业务和事务管理分开,你只需要用注解或XML配置来管理事务。

5.3 说一下Spring的事务传播行为

事务传播行为指的是当存在多个事务时,spring是如何管理这些事务的
可以在配置事务通知中配置事务属性,propagation里面有不同的取值

1. PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新的事务,如果当前有事务,就加入该事务,常用于增删改,也是最常用的传播行为。
2. PROPAGATION_SUPPORTS:支持当前事务,如果当前有事务,就加入该事务,如果没有事务,就以非事务执行。
------上面两种比较常见
3. PROPAGATION_MANDATORY:支持当前事务,如果当前有事务,就加入该事务,如果没有事务,就抛出异常。
4. PROPAGATION_REQUIRES_NEW:创建新事物,无论当前是否存在事务,都创建新事物。
5. PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把事务挂起。
6. PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就抛出异常。
7. PROPAGATION_NESTED:如果当前存在事务,就在嵌套事务内执行,如果没有存在事务,就按照REQUIRED属性执行。

5.4 说一下 spring 的事务隔离?

spring有5大事务隔离级别,默认值为isolation = “default”(使用数据库设置),其它四个隔离级别和数据库隔离级别一致:

  1. default:默认遵从数据库的隔离级别,数据库设置什么我就用什么。
  2. read_uncommitted:未提交读,最低的隔离级别,事务未提交前,可能已经被其它事务读取到(会出现幻读,脏读,不可重复读)
  3. read_committed:提交读,一个事务提交后才能被其它事务读取到(会出现幻读,不可重复读),SQLSevier的默认事务级别
  4. repeatable_read:可重复读,保证多次读取同一个数据时,其值和事务开始时的数据都是一致的,禁止读取到别的事务未被提交的数据(会出现幻读),MySQL默认的事务级别。
  5. serializable:序列化,代价最高最可靠的隔离级别,该隔离级别能防止脏读,不可重复读,幻读。

<mark>名词解释</mark>:

  • 脏读:表示一个事务读取到另外一个事务未提交的数据。例如:事务甲尝试插入数据A,当时还没有提交数据,事务乙就已经查询到了事务甲的数据A。
  • 不可重复读:表示的是在同一个事务两次访问同一个数据可能出现不一样。例如:事务1访问了数据A,此时还没有提交,事务2也访问了数据A,并修改为数据接着提交了。此时事务1再次访问数据就可能出现A或B了。
  • 幻读:所谓幻读时某一个事务读取到某个范围的记录时,另外一个事务也访问了该范围的数据,并且增加了新的数据接着提交了,之前的事务再次读取到该范围的数据时,会出现幻行。
    MySQL中InnoDB存储引擎通过多版本并发控制(MVCC)解决了幻读的问题。

5.5 Spring框架的事务管理有哪些优点?

  1. 为不同的事务API,如JTA,JDBC,HIbernate,JPA等提供一种不变的编程模式
  2. 为编程式事务管理提供一套简单的API而不是复杂的事务API
  3. 支持声明式事务管理
  4. 和spring各种数据访问抽象层很好的集成

5.6 Spring框架的事务管理有哪些优点?

我会选择spring的声明式事务管理,因为它的应用代码量影响最小,更符合一个轻量级容器的思想。声明式事务管理要由于编程式事务管理,虽然比编程式事务管理少了一点灵活性(代码控制事务),还有声明式事务管理只能作用于方法级别的,而编程式事务管理可以作用于代码块级别的。

6. spring的面向切面编程(AOP)

6.1 什么是AOP

OPP是指面向对象编程,运行开发者定义横向和纵向的关系,这将导致了大量的重复代码,不利于各个模块的重用。
AOP:面向切面编程,作为面向对象的补充,用于哪些与业务无关,但却对多个对象产生公共行为和逻辑,抽取并封装成一个可重用模块。这个模块被称为切面,减少系统中的重复代码,降低模块间的耦合度,同时提高了系统间的可维护性,可用于权限认证,日志,事务处理等。

6.2 Spring AOP and AspectJ AOP 有什么区别?AOP 有哪些实现方式?

AOP的实现关键技术在于代理模式,代理模式又分为静态代理和动态代理。
AspectJ AOP 使用的是静态代理,Spring AOP使用的是动态代理。

  • AspectJ是静态代理的增强,所谓静态代理就是AOP框架会在编译阶段生成AOP代理类,因此也成为编译期增强,它会在编译期将Aspect(切面)织入到Java字节码中,运行时候就是增强后的AOP对象
  • Spring AOP使用的就是动态代理,所谓动态代理就是AOP框架不会去修改字节码文件,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含目标对象的全部方法,并且在特定切点处做了增强处理,并回调原对象的方法。

6.3 JDK动态代理和CGLIB动态代理的区别

Java动态代理是利用反射机制生成一个实现代理接口的匿名类,在具体方法前调用InvokeHandler来处理。而CGLIB动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

1. 如果目标对象实现了接口,则默认使用JDK的动态代理实现AOP
2. 如果目标对象使用了,可以强制使用CGLIB实现AOP
3. 如果目标对象没有实现接口,则必须使用CGLIB,spring会自动在CGLIB和JDK动态代理之间切换

如何强制使用CGLIB实现AOP?

  • 添加CGLIB库,SPRING_HOME/cglib/*.jar
  • 在spring配置文件中加入 < aop:aspectj-autoproxy proxy-target-class=“true” />

JDK动态代理和CGLIB动态代理生成字节码的区别

1. JDK动态代理只能对实现接口的类生成代理,不能针对类
2. CGLIB是针对类实现代理,主要是指定的类生成一个子类,覆盖其中方法,因为是继承,所以该类或方法最好不要声明为final

6.4 如何理解 Spring 中的代理?

将Advice应用于目标对象后创建的对象称为代理,在客户端对象情况下,目标对象和代理对象是相同的的。

TargetObject + Advice = Proxy

6.5 解释一下Spring AOP里面的几个名词

  1. 切面(Aspect):切面是通知和切点的结合,通知和切点共同定义了切面的全部内容,在spring AOP中在类上加上@AspectJ来实现。
  2. Joinpoint(连接点):连接点代表这一个个的方法,切面代码可以通过这些点插入到应用程序的正常流程中,并添加新的行为。
  3. Pointcut(切入点):也是代表方法,但是这些方法并没有被增强。
  4. Advice(通知/增强):spring AOP拦截到Joinpoint(连接点)所要做增强过程就是通知。
  5. 引入(Introduction):不修改代码的前提下,运行期我们新的类中添加新的属性或方法
  6. 织入(Weaving):是指把增强应用到目标对象来创建新的代理对象的过程。spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入。简单的说加入事务控制的过程叫做织入。
  7. Proxy(代理):一个类被AOP织入增强后,就产生结果代理类,其实就是代理对象。
  8. Target(目标对象):代理目标对象,就是被代理对象。

6.6 Spring通知有哪些类型?

在AOP属于中,切面的工作被称为通知,实际上是程序执行时要通过spring AOP框架触发的代码段。
spring可以又5中通知类型:

  1. 前置通知(Before):在目标方法被调用之前调用此方法。
  2. 后置通知(After):在目标方法调用完成后执行。
  3. 最终通知(After-returning):目标方法成功执行之后执行。
  4. 异常通知(After-throwing):在目标方法抛出异常后调用通知。
  5. 环绕通知(Around):通知包裹被通知的方法,在被通知调用之前和调用之后执行自定义的行为。

但是spring AOP又两种不一样的通知执行顺序:

1.invoke 方法中没有异常抛出
	1. 前置通知
	2. 方法执行
	3. 后置通知
	3. 最终通知
2.invoke 方法中有异常抛出
	1. 前置通知
	2. 方法执行
	3. 异常通知通知
	3. 最终通知

6.7 什么是切面 Aspect?

Aspect由Advice 和 pointcut组成,切面是通知点和切入点的组合,它既包含了横切逻辑的定义,也包含了连接点的定义,spring AOP就是负责实现切面的框架,它将切面定义的横切逻辑编织到切面所定义的连接点中。
AOP的工作重心在于如何将增强编织目标对象的连接点。这里包含两个工作:

  • 如何通过Advice 和 pointcut定义到特定的jointpoint上
  • 如何在advice上编写代码

可以简单的认为,使用@Aspect注解的类就是一个切面