1 Spring AOP的实现原理?SpringAOP中动态代理的理解?(必会)
AOP,一般称为面向切面编程,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect). SpringAOP 使用的动态代理,所谓的动态代理就是说 AOP 框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个 AOP 对象,这个AOP 对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
Spring AOP 中的动态代理主要有两种方式,JDK 动态代理和 CGLIB 动态代理:
(1)JDK 动态代理只提供接口代理,不支持类代理,核心 InvocationHandler 接口和Proxy 类,InvocationHandler 通过 invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起,Proxy 利用 InvocationHandler 动态创建一个符合某一接口的的实例, 生成目标类的代理对象。
(2) 如果代理类没有实现 InvocationHandler 接口,那么 Spring AOP 会选择使用CGLIB 来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现 AOP。CGLIB 是通过继承的方式做的动态代理,因此如果某个类被标记为 final,那么它是无法使用 CGLIB 做动态代理的。
AOP 能做什么:(记录操作日志、缓存处理、Spring中内置的事务处理...)
1、降低模块之间的耦合度
2、使系统容易扩展
3、避免修改业务代码,避免引入重复代码,更好的代码复用
举个例子:需要统计每一个业务方法的执行耗时。
AOP前
AOP后
AOP 怎么用:
@Before 前置通知:某方法调用之前发出通知。
@After后置通知:某方法完成之后发出通知。
@AfterReturning返回后通知:方法正常返回后,调用通知。在方法调用后,正常退出发出通知。
@AfterThrowing异常通知:抛出异常后通知(After throwing advice) : 在方法抛出异常退出时执行的通知。在方法调用时,异常退出发出通知。
@Around环绕通知:通知包裹在被通知的方法的周围知。
2 谈一谈你对IOC的理解? 谈一谈你对DI的理解?
IOC 的意思是控制反转,是指创建对象的控制权的转移,以前创建对象的主动权和时机是由自己把控的,而现在这种权力转移到 Spring 容器中,并由容器根据配置文件去创建实例和管理各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。最直观的表达就是,IOC 让对象的创建不用去 new 了,可以由 spring 根据我们提供的配置文件自动生产,我们需要对象的时候,直接从 Spring 容器中获取即可。
Spring 的配置文件中配置了类的字节码位置及信息, 容器生成的时候加载配置文件识别字节码信息, 通过反射创建类的对象。
DI 的意思是依赖注入,和控制反转是同一个概念的不同角度的描述,即应用程序在运行时依赖 Ioc 容器来动态注入对象需要的外部资源。
有三种注入方式:构造器注入, setter 方法注入, 根据注解注入。
IOC 和 DI 的关系:IOC就是容器,DI 就是注入这一行为,那么 DI 确实就是 IOC 的具体功能的实现。而 IOC则是 DI 发挥的平台和空间。所以说,IOC和 DI 即是相辅相成的搭档,又是殊途同归的双胞胎。最重要的是,他们都是良好的降低耦合的思想。
3 Spring 的生命周期?(高薪常问)
① 通过 BeanDefinition 获取 bean 的定义信息② 调用构造函数实例化 bean③ bean 的依赖注入④ 处理 Aware 接口 ( BeanNameAware 、 BeanFactoryAware 、 ApplicationContextAware )⑤ Bean 的后置处理器 BeanPostProcessor - 前置⑥ 初始化方法 ( InitializingBean 、 init -method)⑦ Bean 的后置处理器 BeanPostProcessor - 后置⑧ 销毁 bean![]()
4 Spring 中 bean 的作用域有哪些?(必会)
Spring 支持如下 5 种作用域:
(1)singleton:默认作用域,单例 bean,每个容器中只有一个 bean 的实例。
(2)prototype:每次请求都会为 bean 创建实例。
(3)request:为每一个 request 请求创建一个实例,在请求完成以后,bean 会失效 并被垃圾回收器回收。
(4)session:与 request 范围类似,同一个 session 会话共享一个实例,不同会话 使用不同的实例。
(5)global-session:全局作用域,所有会话共享一个实例。如果想要声明让所有会 话共享的存储变量的话,那么这全局变量需要存储在 global-session 中。
作用域 | 说明 |
singleton | 容器内同名称的bean只有一个实例(单例)(默认) |
prototype | 每次使用该bean时会创建新的实例(非单例) |
request | 每个请求范围内会创建新的实例(web环境中,了解) |
session | 每个会话范围内会创建新的实例(web环境中,了解) |
global-session(application) | 每个应用范围内会创建新的实例(web环境中,了解) |
5 BeanFactory 和 ApplicationContext 有什么区别(了解)
BeanFactory: Spring 最顶层的接口,实现了 Spring 容器的最基础的一些功能, 调用起来比较麻 烦, 一般面向 Spring 自身使用 BeanFactory 在启动的时候不会去实例化 Bean,从容器中拿 Bean 的时候才会去 实例化
ApplicationContext: 是 BeanFactory 的子接口,扩展了其功能, 一般面向程序员身使用ApplicationContext 在启动的时候就把所有的 Bean 全部实例化
6 Spring 框架中都用到了哪些设计模式?(必会)
1. 工厂模式:BeanFactory 就是简单工厂模式的体现,用来创建对象的实例
2. 单例模式:Bean 默认为单例模式
3. 代理模式:Spring 的 AOP 功能用到了 JDK 的动态代理和 CGLIB 字节码生成技术
4. 模板方法 :用来解决代码重 复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate
5. 观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依 赖于它的对象都会得到通知被制动更新,如Spring中listener的实现ApplicationListener
7 Spring 事务的实现方式和实现原理(必会)
Spring 事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring 是无法提供事务功能的。真正的数据库层的事务提交和回滚是通过 binlog 或者 redo log 实现的。
spring 事务实现主要有两种方法
1、编程式,beginTransaction()、commit()、rollback()等事务管理相关的方法
2、声明式,利用注解 Transactional 或者 aop 配置
8 Spring 的对象默认是单例的还是多例的? 单例 bean 存不存在线程安全问题呢?(必会)
1. 在 spring 中的对象默认是单例的,但是也可以配置为多例。
2. 单例 bean 对象对应的类存在可变的成员变量并且其中存在改变这个变量的线程时,多线程操作该 bean 对象时会出现线程安全问题。
原因是:多线程操作如果改变成员变量,其他线程无法访问该 bean 对象,造成数据混乱。
解决办法:在 bean 对象中避免定义可变成员变量; 在 bean 对象中定义一个 ThreadLocal 成员变量,将需要的可变成员变量 保存在 ThreadLocal 中。
10 @Resource 和@Autowired 依赖注入的区别是什么? @Qualifier 使用场景是什么?(了解)
@Resource
只能放在属性上,表示先按照属性名匹配 IOC 容器中对象 id 给属性注入值若没有 成功,会继续根据当前属性的类型匹配 IOC 容器中同类型对象来注入值 若指定了 name 属性@Resource(name = "对象 id"),则只能按照对象 id 注入值。
@Autowird
放在属性上:表示先按照类型给属性注入值如果 IOC 容器中存在多个与属性同类 型的对象,则会按照属性名注入值 也可以配合@Qualifier("IOC 容器中对象 id")注解直接按照名称注入值。
放在方法上:表示自动执行当前方法,如果方法有参数,会自动从 IOC 容器中寻 找同类型的对象给参数传值
也可以在参数上添加@Qualifier("IOC 容器中对象 id")注解按照名称寻找对象给 参数传值。
@Qualifier 使用场景:
@Qualifier("IOC 容器中对象 id")可以配合@Autowird 一起使用, 表示根据指定 的 id 在 Spring 容器中匹配对象
11 Spring 的常用注解(必会)
1. @Component(任何层) @Controller @Service @Repository(dao): 用于 实例化对象
2. @Scope : 设置 Spring 对象的作用域
3. @PostConstruct @PreDestroy : 用于设置 Spring 创建对象在对象创建之后和销 毁之前要执行的方法
4. @Value: 简单属性的依赖注入
5. @Autowired: 对象属性的依赖注入
6. @Qualifier: 要和@Autowired 联合使用,代表在按照类型匹配的基础上,再按照 名称匹配。
7. @Resource 按照属性名称依赖注入
8. @ComponentScan: 组件扫描
9. @Bean: 表在方法上,用于将方法的返回值对象放入容器
10. @PropertySource: 用于引入其它的 properties 配置文件
11. @Import: 在一个配置类中导入其它配置类的内容
12. @Configuration: 被此注解标注的类,会被 Spring 认为是配置类。Spring 在启动 的时候会自动扫描并加载所有配置类,然后将配置 类中 bean 放入容器
13. @Transactional 此注解可以标在类上,也可以表在方法上,表示当前类中的方法 具有事务管理功能。
12 Spring 的事务传播行为(高薪常问)
spring 事务的传播行为说的是,当多个事务同时存在的时候,spring 如何处理这些事 务的行为。
备注(方便记忆): propagation 传播 require 必须的/suppor 支持/mandatory 强制托管/requires-new 需要新建/not -supported 不支持/never 从不/nested 嵌套的
① PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前 存在事务,就加入该事务,该设置是最常用的设置。
② PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务, 如果当前不存在事务,就以非事务执行。
③ PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事 务,如果当前不存在事务,就抛出异常。
④ PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建 新事务。
⑤ PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务, 就把当前事务挂起。
⑥ PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
⑦ PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前 没有事务,则按 REQUIRED 属性执行。
13 Spring 中的隔离级别 (高薪常问)
ISOLATION 隔离的意思
① ISOLATION_DEFAULT:这是个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别。
② ISOLATION_READ_UNCOMMITTED:读未提交,允许另外一个事务可以看到这个事务未提交的数据。
③ ISOLATION_READ_COMMITTED:读已提交,保证一个事务修改的数据提交后才能被另一事务读取,而且能看到该事务对已有记录的更新。解决脏读问题
④ ISOLATION_REPEATABLE_READ:可重复读,保证一个事务修改的数据提交后才能被另一事务读取,但是不能看到该事务对已有记录的更新。行锁 5152
⑤ ISOLATION_SERIALIZABLE:一个事务在执行的过程中完全看不到其他事务对数据
库所做的更新。表锁