根据老师上课内容,自己对学习的整理
SpringAOP
在软件业,AOP为Aspect Oriented Progamming的缩写,意为:
面向切面编程,通过预编译和运行期间动态代理实现程序功能的统一维护的一种技术
AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合性降低,提高程序的可重用性,同时提高了开发的效率
AOP主要作用:在不修改原有代码的条件下对方法进行扩展
难点:
切面:类似汉堡包,上面是事务,中间是业务方法
预编译:预编译是做些代码文本的替换工作。是整个编译过程的最先做的工作【百度百科】
类似static,静态资源会被优先加载
动态代理:通过第三方代理,JDK代理或者CGLib代理
IOC-DI/AOP之间的区别
1.IOC-DI利用第三方容器将对象统一管理,利用依赖注入为属性赋值,解决了对象与对象之间的耦合性的问题
进阶:SpringMVC框架(对象)/Mybatis框架(对象)类似的框架都可以交给Spring容器管理。Spring可以以统一的方法管理其他第三方的框架,使得调用浑然一体,降低耦合,解决框架与框架之间的耦合问题
2.AOP名称为面向切面编程,使得业务逻辑各部分之间的耦合度降低
动态代理
动态代理的作用:使用代理机制可以有效降低代码耦合性,将公共的代码/重复的代码,写在代理机制中,通过代理机制调用方法,使得真实的业务被调用。通过调用机制,可以有效的降低业务之间的耦合
代理机制 Service
事务开始
用户---> 目标方法调用 ---> 业务方法
事务提交
动态代理分类
代理特点:使用代理对象和是使用目标方法一样(高仿)
JDK代理
1.jdk动态代理是JDK源码提供的,无需导入额外的jar包
2.JDK代理对象要求实现和被代理相同的接口 必须有接口
3.JDK代理创建速度快,运行时稍慢
CGLib代理
1.cglib动态代理需要导入额外的包才能使用。
2.cglib要求被代理者可以没有接口,但是cglib代理对象是目标对象的子类(继承)
3.cglib创建对象时较慢,但是运行期速度快。
AOP 重点,面试必问
AOP底层实现就是JDK代理和CGLib代理
Spring中的AOP也是利用代理对象在不修改源码的情况下,对方法进行扩展
首先需要导入Jar包,在pom文件中
<!--引入AOPjar包文件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
编辑切面类
注解:
@Aspect标识当前类是一个切面
@Pointcut标识切入点表达式
切入点表达式
*号是通配符,表示任意
bean标签
bean("对象的ID")只能匹配固定的类/对象一个 粗粒度
within表达式
within(包名.类名)可以匹配多个类 粗粒度
execution表达式 细粒度
@Pointcut("execution(* com.*..*(..))")
匹配com包下任意类任意方法任意参数 任意返回值的方法
execution(返回值类型 包名.类名.方法名(参数列表))
@annotation
@Pointcut("annotation(路径.注解)")
使用注解拦截
@Before前置通知
在执行方法前执行
@AfterReturning后置通知
在执行方法后执行
@After最终通知 基本不用
不管目标方法执行是否正确,都要执行(类似try-catch中的finally)
@AfterThrowing 异常通知
目标方法执行时,抛出异常
@Around 环绕通知(类似包括前置通知后置通知的整合)
环绕通知必须提供参数,并且必须位于通知的第一位
前四大通知类型不能控制目标方法的运行,一般记录程序的运行状态
在目标方法执行前后都要运行,只有环绕通知才可以控制目标方法运行,使用最多的通知方法
@EnableAspectJAutoProxy让AOP生效,写在配置类中
可以添加属性(proxyTargetClass=true)让代理默认为CGLib代理,不建议使用默认为jdk代理,因为不是所有类都有接口。
@Order(value=数字)
给切面类排序,数字越小,越先执行
关于JoinPoint和ProceedingJoinPoint区别
说明:
1.ProceedingJoinPoint只适用于环绕通知,因为只有环绕通知,才能控制目标方法的运行.
2.JoinPoint 适用于其它的四大通知类型,可以用来记录运行的数据.
3. ProceedingJoinPoint 中有特殊的方法proceed();
4. 如果使用"JoinPoint" 则必须位于参数的第一位