什么是AOP
AOP即面向切面编程。可以将那些与业务无关,却为业务模块所共同调用的逻辑或责任(比如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块之间的耦合度,有利于未来的可扩展性和可维护性。
SpringAOP是基于动态代理的,如果要代理的对象实现了某个接口,那么SpringAOP就会使用JDK动态代理去创建对象。而对于没有实现接口的对象,就无法使用JDK动态代理,转而用CGlib动态代理生成一个被代理对象的子类来作为代理。
使用AOP之后,我们可以把一些通用功能抽象出来,在需要用到的地方直接用就行。这样可以大大减少代码量。要是需要增加新功能也很方便,提高了系统的扩展性。
日志功能、事务管理和权限管理等场景都用到了AOP。
AOP的一些基本概念
- 连接点:可以被增强的方法
- 切入点:被增强的方法
- 通知:增强的方法或逻辑
- 切面:对象与对象之间,方法与方法之间,模块与模块之间都是一个个切面。(切入点和通知的绑定)
- 目标对象:被一个或多个切面所通知的对象
- AOP代理(AOP Proxy):在SpringAOP中有两种代理方式,JDK动态代理和GCLIB代理
AOP的代理有几种方式(AOP的实现原理)?
AOP思想的实现一般都是基于代理模式,在Java中一般采用JDK动态代理模式。但JDK动态代理只能代理接口而不能代理类。所以AOP会按照两种情况就行切换
- 如果目标对象的实现类实现了接口,SpringAOP将会采用JDK动态代理来生成AOP代理类
- 如果目标对象的实现类没有实现接口,SpringAOP将会采用CGLIB来生成AOP代理类。
AOP主要用在哪些场景?
- 事务管理
- 日志
- 性能监视
- 安全检查
- 缓存
Spring框架中的单例bean是线程安全的吗?
单例bean存在线程问题,主要是因为当多个线程操作同一个对象时,对这个对象的非静态成员变量的写操作存在线程安全问题。
有两种常见的解决方案
1.在bean对象中尽量避免定义可变的成员变量。(不太现实)
2.在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在ThreadLocal中。
Spring事务管理方式?
- 编程式事务:在代码中硬编码
- 声明式事务:在配置文件中配置
声明式事务又分为:
- 基于XML的声明式事务、
- 基于注解的声明式事务
Spring中的事务隔离级别?
TransactionDefinition接口中定义了五个表示隔离级别的常量:
- TransactionDefinition.ISOLATION_DEFAULT:使用后端数据库默认的隔离级别,MySQL默认采用的REPEATABLE_READ隔离级别,Oracle默认采用的READ_COMMITTED隔离级别。
- TransactionDefinition.ISOLATION_READ_UNCOMMITTED:最低的隔离级别,允许尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
- TransactionDefinition.ISOLATION_READ_COMMITTED:允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
- TransactionDefinition.ISOLATION_REPEATABLE_READ:对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
- TransactionDefinition.ISOLATION_SERIALIZABLE:最高的隔离级别,完全服从于ACID的隔离级别。所以的事务依次逐个进行,这样事务就不可能产生干扰。即该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下不会用到该级别。