Spring Aop详解
Spring aop详解
spring aop 的概述
- aop 面向切面(方面)编程,扩展功能不修改源代码的实现。
- aop采取的是横向抽取机制,取代了传统纵向继承体系重复代码(性能监视、事物管理、安全检查、缓存)
Aop 的原理
public class User {
//添加用户的方法
public void add() {}
public void update() {}
public void delete() {}
public void findAll() {}
/**
* 扩展功能
* 1.添加用户之后,添加日志功能
* 2.添加之后,记录什么时间添加了那个用户
*/
}
-
切面(Aspect):
一个关注点的模块化,这个关注点可能会横切多个对象。事务管理是J2EE应用中一个关于横切关注点的很好的例子。在Spring AOP中,切面可以使用基于模式或者基于@Aspect注解的方式来实现。 -
连接点(Joinpoint): 类里面哪些方法可以被增强的,这些方法称为连接点
-
通知(Advice)
实际增强的逻辑,称为增强,比如扩展日志的功能,这个日志功能叫做通知,也称为增强
通知称为:前置通知,后置通知,最终通知,环绕通知 -
切入点(Pointcut)
在类里面有很多方法被增强,比如实际操作中,只是增强了类里面的add方法和update方法,实际增强的方法称为切入点。 -
引入(Introduction)
用来给一个类型声明额外的方法或属性(也被称为连接类型声明(inter-type declaration))。Spring允许引入新的接口(以及一个对应的实现)到任何被代理的对象。例如,你可以使用引入来使一个bean实现IsModified接口,以便简化缓存机制。 -
目标对象(Target Object)
被一个或者多个切面所通知的对象。也被称做被通知(advised)对象。 既然Spring AOP是通过运行时代理实现的,这个对象永远是一个被代理(proxied)对象。 -
AOP代理(AOP Proxy)
AOP框架创建的对象,用来实现切面契约(例如通知方法执行等等)。在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。 -
织入(Weaving)
把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。这些可以在编译时(例如使用AspectJ编译器),类加载时和运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。
Aop 的操作
在spring里面进行aop操作,进行aspectj实现
- aspectjz不是spring的一部分,spring使用aspectj一起使用进行aop操作。
- spring2.0以后新增了Aspectj支持
使用aspect实现aop有两种方式
- 基于aspectj的xml配置
- 基于aspectj的注解方式
(1)基于配置实现SpringAop
使用execution(<访问修饰符?<返回类型><方法名>(<参数>)<异常>)
- execution(* con.springaop.Book.add(…))
- execution(* con.springaop.Book.*(…))book的所有返回值类型的所有方法
- execution(* .(…))所有路径所有返回值的所有方法
- execution(* .save(…)) 配置所有以save开头的方法
aop xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--配置对象 -->
<bean id="book" class="springaop.book.Book"/>
<bean id="myBook" class="springaop.book.MyBook"/>
<!--配置aop-->
<aop:config>
<!-- 配置切入点-->
<aop:pointcut id="pointcut1" expression="execution(* springaop.book.*.*(..))"/>
<!-- 配置切面 把增强应用方法上面去 -->
<aop:aspect id="aspect" ref="myBook">
<aop:before method="beforeAdvice" pointcut-ref="pointcut1"/>
<aop:after method="afterAdvice" pointcut-ref="pointcut1"/>
<aop:around method="aroundAdvice" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
</beans>
package springaop.book;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyBook {
public void beforeAdvice() {
System.out.println("前置通知");
}
public void afterAdvice() {
System.out.println("后置通知");
}
/**
* proceedingJoinPoint是一个切入点,被增强的方法
* @param proceedingJoinPoint
* @throws Throwable
*/
public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕通知");
proceedingJoinPoint.proceed();
System.out.println("环绕通知1");
}
public void finalAdvice() {
System.out.println("最终通知");
}
public void execptionAdvice() {
System.out.println("异常通知");
}
}
这里一定要注意环绕通知,如果环绕通知只是写逻辑操作,没有调用proceedingJoinPoint.proceed();方法是不会调用方法的,所以需要调用切入点的该方法
(2)基于注解实现SpringAop
这里一定要在配置文件开启aop代理还有开启注解
@Aspect
@Component("bookAspect")
public class BookAspect {
@Pointcut(value = "execution(* springaop2.Book.*(..))")
public void pointCut() {
System.out.println("-----pointCut------");
}
@Before("pointCut()")
public void beforeAdvice() {
System.out.println("-----beforeAdvice-----");
}
@After("pointCut()")
public void afterAdvice() {
System.out.println("-----afterAdvice-----");
}
@Around("pointCut()")
public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("-----start--aroundAdvice---");
proceedingJoinPoint.proceed();
System.out.println("-----end--aroundAdvice---");
}
}
本文作者:志旋
本文链接:https://www.cnblogs.com/wuzhixuan/p/12890670.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步