spring aop

  1. spring 结合msql 数据库事物分析 (spring想要实现事物必须要建立连接池)

a. 数据库事物的基本特性 ACID
原子性 atomicity 事物中的各项操作 要么全做 要么全不做,任何一项操作的失败都会导致食物的失败
一致性 consitency 事物结束后系统状态是一致的
隔离性 isolationv 并发执行的事物无法看到对方的中间状态
持久性 durabilit 事物完成者之后所由的改动都会被持久化 即使发生灾难性的失败

b 隔离级别
在高并发的情况下 要完全保证其ACID特性是非常困难的,除非把所有的事物串行话执行,但带来的负面的影响 将是性能大打折扣,所以数据库设计了四种隔离级别共用户选择
在这里插入图片描述mySql 默认级别是 Repeatable read
oracle 默认级别是 Read commited
查看隔离级别 语句 select@@tx_isolation

c.Spring事物相关API Spring 提供了三个接口使用事物 (可看代码去了解)
TransactionDefinition 事物的定义 (主要是隔离级别相关)在这里插入图片描述

PlatformTransactionManage 事物管理(事物的提交 会滚 获取事物)
在这里插入图片描述

TransactionStatus 事物运行状态(事物会滚刷新)
在这里插入图片描述
d.事物的传播机制
常见的是 PROPAGATION_REQUIRED(propagation_required) PROPAGATION_NOT_SUPPORTED PROPAGATION_REQUIRED_NEW
在这里插入图片描述举例
在这里插入图片描述

总结:
支持当前事物 (你是支持我就支持,你不支持我也不支持 父唱妇随 required 有我就加入没有我就新建),
不支持当前事物(不管怎么样就是不支持事物,有事物也把你挂起, required-new ,你有事物就把你事物取消 ,但是我要新建事物),

2.spring Aop 常见面试题
a. 什么事AOP ?
答: 与oop 相比面向切面 传统的oop 开发代码逻辑都是至向而下的过程会产生一些横切问题 比如权限,日志,这些会出现在我们代码的各个角落 ,而AOP 就是把这些非业务代码剥离出来 完成解偶,是代码的重用性和开发效率提高

b.AOP 的应用场景
答:日志记录 权限认证 事物管理 效率检查(代码执行时间)…

c.spring Aop 底层技术
答:

  • JDK 动态代理 (基于接口 实现接口原因 底层生成的代理类已经继承proxy 不能多继承)

  • CGLIB 代理 (基于继承)

  • 如果有人问Spring AOP 底层代码是那种代理 ? 进入源码找答案往下看 源码分析

  • 这两种代理什么时候织入(增强)的(增强代码 加入日志) 编译时候织入 还是运行时候织入(增强)?

  • 初始化时期织入(增强) 还是获取对象时候织入(增强)?
    AOP有三种织入方式:①编译期织入:需要特殊的Java编译期(例如AspectJ的ajc);②装载期织入:要求使用特殊的类加载器,在装载类的时候对类进行增强;③运行时织入:在运行时为目标类生成代理实现增强。Spring采用了动态代理的方式实现了运行时织入,而AspectJ采用了编译期织入和装载期织入的方式。

d.springAOP 和ASpectJ的关系
答 : 1.spring AOP(面向方法级别),
提供两种编程风格 :
- [Aspectj support ] : 利用Aspectj 的注解 启动类加入
@EnableAspectJAutoProxy(true cglib代理 默认是false jdk代理 源码里面config.isProxyTargetClass() 判断的)
- [Schema-based AOP support] : xml 配置文件加入 aop:aspectj-autoproxy/
,
2.ASpectJ:类似一种语法 Aop 去使用语法风格和方式

e.Spring AOP的应用(可以看Spring 官网介绍,例子:具体可以看下后台清缓存)
[Aspectj support ]
(1.) aspect (@aspect 切面) 一定要给Spring去管理
切面是由切点和增强(引介)组成的,它包括了对横切关注功能的定义,也包括了对连接点的定义。
Pointcut 切点 表示连接点集合 (@Pointcut 里面很多表达式如下 百度看看吧 )
如果连接点相当于数据中的记录,那么切点相当于查询条件,一个切点可以匹配多个连接点。Spring AOP的规则解析引擎负责解析切点所设定的查询条件,找到对应的连接点。
[execute 最小粒度到方法]
以set开始的方法 execution(* set*(…))
execution(* cn.freemethod.business.pack.Say.(…)) 定义在cn.freemethod.business.pack.Say接口中的方法
execution(
cn.freemethod.business..(…)) 任何cn.freemethod.business包中的方法
execution(* cn.freemethod.business….(…))任何定义在cn.freemethod.business包或者其子包中的方法
[within 最小粒度到类]
[this 当前代理类( proxy class) 因为当前类是 extends Proxy implements dao 并不是当前的目标类.
但是 如果使用cglib 代理 就可以]
[target 代理的目标类( target class)]
[args 表达式到的作用是匹配指定参数类型和制定参数数量的方法 与报名类名无关]
[@annotation 注解作用与方法级别]

以上所有表达式都是有@注解 比如@within ,也都可以混用比如 (pointCutExecution() && !pointCutAnnotation() 某个类下面所有,但是不包含某个注解下面的方法)

上述都可以走代码去验证一下

join point 连接点 (目标对象的方法,cn.freemethod.business.pack.Say接口 里面的方法)
程序执行的某个特定位置(如:某个方法调用前、调用后,方法抛出异常后)。一个类或一段程序代码拥有一些具有边界性质的特定点,这些代码中的特定点就是连接点。Spring仅支持方法的连接点
weaving 把代理逻辑加入到目标对象的过程的增强
织入是将增强添加到目标类具体连接点上的过程,AOP有三种织入方式:①编译期织入:需要特殊的Java编译期(例如AspectJ的ajc);②装载期织入:要求使用特殊的类加载器,在装载类的时候对类进行增强;③运行时织入:在运行时为目标类生成代理实现增强。Spring采用了动态代理的方式实现了运行时织入,而AspectJ采用了编译期织入和装载期织入的方式。

  • advice 通知/织入 (通过切面aspect 里的切点 support<可以具体到某个包 某个类 某个方法.就是所谓的 join point>,在这个之前或者之后做通知advice <比如清缓存> )

(1)前置通知 berfore
(2)后置通知 after
(3)环绕通知 Around advice
(4)异常通知 after throw
(5)最终通知 after finally

JoinPoint 和ProceedingJoinPoint有什么区别
答:ProceedingJoinPoint 继承了Joinpoint 可以执行目标方法
JoinPoint 代理目标类 但是执行不了目标方法

例子:
@Aspect
@Component
public class AppAspect {
@Pointcut(“execution(* com.king.aop.dao..(…))”) //任何com.king.aop.dao包中的方法 (query()放法)
public void pointCut(){
}
@After(“com.king.aop.config.AppAspect.pointCut()”)
public void after(){
//dao query()方法之后做什么
System.out.println(“com.king.aop.dao.TestDao.query()方法之后做什么”);
}
@Before(“com.king.aop.config.AppAspect.pointCut()”)
public void before(){
//dao query()方之前做什么
System.out.println(“com.king.aop.dao.TestDao.query() 之前做什么”);
}
@AfterThrowing(“com.king.aop.config.AppAspect.pointCut()”)
public void exceptionInfo(){
System.out.println(“com.king.aop.dao.TestDao.query() 抛异常做什么”);
}
}
@Component
public class TestDao {
public void query(){
System.out.println(“king is good man”);
}
}

f. spring Aop的源码分析

Spring aop 默认走的是那种代理 是cglib 还是 jdk 动态代理?
答:看条件
1.继承的话 cglib
采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。(利用ASM开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理)
在这里插入图片描述

在这里插入图片描述
2. 如果实现了接口 走的是jdk动态代理 在 bean 注入到ioc容器里面的时候就已经形成了注入 完成代理
源码分析
AbstractAutowireCapableBeanFactory .doCreateBean (){ //ioc 创建bean 就是最总是由他创建的
exposedObject = initializeBean(beanName, exposedObject, mbd){ //初始化bean实力
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName){// 初始化bean 之后处理
Object current = processor.postProcessAfterInitialization(result, beanName){ //完成了 代理
AbstractAutoProxyCreator //实现类.postProcessAfterInitialization(){
return this.wrapIfNecessary(bean, beanName, cacheKey){// 进行代理包装重点方法
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean() {} //拦截器 获取类信息
Object proxy = this.createProxy(){创建代理
proxyFactory.getProxy(this.getProxyClassLoader()){ //通过代理工厂创建
CglibAopProxy/JdkDynamicAopProxy= this.createAopProxy().getProxy(classLoader){ //核心
createAopProxy(){
this.getAopProxyFactory().createAopProxy(){
DefaultAopProxyFactory.createAopProxy() { //实现类进行判断创建到底是cglib 还是jdk
if ( !config.isProxyTargetClass() //默认是fasle ) {
return new JdkDynamicAopProxy(config);
} else {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException()
} else {
return (AopProxy)(!targetClass.isInterface() &&
!Proxy.isProxyClass(targetClass) ?
new ObjenesisCglibAopProxy(config) :
new JdkDynamicAopProxy(config));
}
JdkDynamicAopProxy = createAopProxy() .getProxy( ){
Proxy.newProxyInstance(classLoader, proxiedInterfaces, this){
//jdk 底层源码 代理代码
}
}
}
在这里插入图片描述
在这里插入图片描述

g.JDK动态代理与CGLib代理的区别是什么?

原理区别:
java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。核心是实现InvocationHandler接口,使用invoke()方法进行面向切面的处理,调用相应的通知。
而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。核心是实现MethodInterceptor接口,使用intercept()方法进行面向切面的处理,调用相应的通知。

性能区别:
1、CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,在jdk6之前比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。
2、在jdk6、jdk7、jdk8逐步对JDK动态代理优化之后,在调用次数较少的情况下,JDK代理效率高于CGLIB代理效率,只有当进行大量调用的时候,jdk6和jdk7比CGLIB代理效率低一点,但是到jdk8的时候,jdk代理效率高于CGLIB代理。

各自局限:
1、JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理。
2、cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值