网站制作多少钱400,网络网站建设价格,wordpress用户名密码注册,顺德网站文章目录 1. 前言2. 什么是AOP3. AOP快速入门4. AOP的核心概念5. 切点表达式6. 切点函数7. 通知8. 总结 1. 前言
本文围绕AOP进行讲解,AOP可以做什么,涉及到了哪些注解,以及各个注解运行的时机,以及Around相较于其它注解有什么不同,并且如果要执行目标方法需要怎么做
2. 什么… 文章目录 1. 前言2. 什么是AOP3. AOP快速入门4. AOP的核心概念5. 切点表达式6. 切点函数7. 通知8. 总结 1. 前言
本文围绕AOP进行讲解,AOP可以做什么,涉及到了哪些注解,以及各个注解运行的时机,以及Around相较于其它注解有什么不同,并且如果要执行目标方法需要怎么做
2. 什么是AOP Spring的AOP面向切面编程是Spring框架的一个重要特性它允许开发人员在应用程序中通过定义切面来实现横切关注点的功能如日志记录、性能监控、事务管理等。AOP通过将这些关注点从业务逻辑中抽离出来使得代码更加模块化、可维护和可重用。 SpringAOP就是批量对Spring容器中bean的方法做增强并且这种增强不会与原来方法中的代码耦合
3. AOP快速入门
目标:要求service包下所有的类中的方法调用前输出: “方法被调用了”
在学AOP前,大家可能会在每个方法内添加一个输出语句. 但如果类很多,类中的方法也很多,添加起来也很麻烦,而且如果后续要进行修改,也很麻烦
首先要引入相关依赖:
dependenciesdependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.3.29/version/dependencydependencygroupIdorg.aspectj/groupIdartifactIdaspectjweaver/artifactIdversion1.9.7/version/dependency
/dependencies 把相关bean放到Spring容器中
可以使用注解ComponentScan(basePackages com.example),也可以在xml配置文件中,使用context:component-scanbase-packagecom.example/context:component-scan 因为我的代码结构是这样的,所以是com.example.
实现AOP
实现AOP可以使用注解,也可以使用xml配置文件. 因为是入门,所以先认识一下注解实现AOP的方式
①开启AOP注解支持
aop:aspectj-autoproxy/aop:aspectj-autoproxy②创建切换类
其实就是普通的类,加上Component和x Aspect这两个注解而已
使用使用Pointcut注解来指定要被强的方法 使用Before注解来给我们的增湿代码所在的方法进行标识并且指定了增强代码是在被增强方法执行之前执行 的。
示例:
Component
Aspect
public class MyAspect {Pointcut(execution(* com.example.service.*.*(..)))public void point(){}Before(point())public void methodBefore(){System.out.println(方法被调用了);}
}Pointcut(execution(* com.example.service.*.*(..)))这段代码:是指 对com.example的service包下类的所有方法进行增强 Before(point())public void methodBefore(){System.out.println(方法被调用了);}Before(point())是指选中point()这个切点表达式的方法进行增强,增强的内容就是方法中的代码
UserService:
Service
public class UserService {public void update(){System.out.println(执行了UserService的update方法);}
}准备工作完成,进行测试. 可以看到在执行UserService的update()方法前,输出了方法被调用了
4. AOP的核心概念
Joinpoint (连接点): 所谓连接点是指那些可以被增强到的点。在spring中,这些点指的是方法因为spring 只支持方法类型的连接点⭐Pointcut (切入点) : 所谓切入点是指被增强的连接点(方法)Advice (通知/ 增强) : 所谓通知是指具体增强的代码Target (目标对象): 被增强的对象就是目标对象Aspect (切面) : 是切入点和通知(引介) 的结合Proxy (代理) : 一个类被 AOP 增强后就产生一个结果代理类
5. 切点表达式
切点表达式用来表示要对哪些方法进行增强
写法: execution([修饰符] 返回值类型 包名.类名.方法名(参数))
访问修饰符可以省略,大部分情况下可以省略返回值类型、包名、类名、方法名可以使用星号* 代表任意包名与类名之间一个点.代表当前包下的类两个点..表示当前包及其子包下的类参数列表可以使用两个点..表示任意个数任意类型的参数列表
如快速入门中的切点表达式:
execution(* com.example.service.*.*(..))该切点表达式就是 对com.example的service包下类的所有方法进行增强,
6. 切点函数
我们也可以在要增强的方法上加上注解。然后使用annotation来表示对加了什么注解的方法进行增强。
示例:
首先自定义一个注解,在创建类时选择Annotation
public interface MyComment{}注意此时是不能直接用,我们需要添加几个注解 不知道添加什么也很好办,可以直接写一个注解,点击看源码
Retention(RetentionPolicy.RUNTIME): 表示注解可以保持到什么时期,RUNTIME就是运行时Target({ElementType.METHOD}): 表示此注解可以添加到哪些东西方法,METHOD就是方法 直接将注解添加到我们自定义的注解上即可 使用自定义注解,直接在相应的方法中添加即可: 此时的切点就不能像之前那样写了,需要使用annotation注解,并加上自定义注解的全类名 此时运行代码同样可以看到userService中的方法被增强了. 其实这种方式的AOP增强比使用切点表达式灵活多了.
7. 通知
SpingAOP的通知共有五种:
Before: 前置通知在方法执行前执行AfterReturning: 返回后通知在目标方法执行后执行如果出现异常不会执行After: 后置通知在目标方法返回结果之后执行无论是否出现异常都会执行AfterThrowing: 异常通知在目标方法抛出异常后执行Around: 环绕通知围绕着方法执行
Before,AfterReturning和After方法使用起来很简单,只需要知道加了这些注解的方法是在什么时候增强的即可
示例:
Component
Aspect
public class MyAspect {Pointcut(annotation(com.example.aspect.MyComment))public void point(){}Before(point())public void methodBefore(){System.out.println(Before);}AfterReturning(point())public void methodAfterReturning(){System.out.println(AfterReturning);}After(point())public void methodAfter(){System.out.println(After);}
}Service
public class UserService {MyCommentpublic void update(){System.out.println(执行了UserService的update方法);}
}注意:AfterReturning 如果方法中异常不会执行❗
AfterThrowing恰恰相反,只有出现异常才会执行
在切面类中增加 AfterThrowing注解的方法 AfterThrowing(point())public void methodAfterThrowing(){System.out.println(AfterThrowing);}让需要增加的方法报错
Service
public class UserService {MyCommentpublic void update(){System.out.println(执行了UserService的update方法);System.out.println(1/0);}
}执行结果:
可以看到没有执行AfterReturning相应的方法,而是执行了AfterThrowing相应的方法
以上注解都比较简单,只需要知道他们运行的时机即可,重中之重还是Around
切面类:
Component
Aspect
public class MyAspect {Pointcut(annotation(com.example.aspect.MyComment))public void point(){}Around(point())public void methodAround(){System.out.println(Around);}
}切点
Service
public class UserService {MyCommentpublic void update(){System.out.println(执行了UserService的update方法);}
}运行结果:
虽然执行了Around相应的方法,但是结果中并没有UserService中的对应的输出语句,这是为什么? 这就是Around的奇妙之处了
如果想要目标方法执行,需要添加一个ProceedingJoinPoint类型的参数,同时调用里面的proceed()方法:
Around(point())
public void methodAround(ProceedingJoinPoint joinPoint){System.out.println(Around);try {joinPoint.proceed();} catch (Throwable e) {throw new RuntimeException(e);}
}此时就可以正常执行目标方法了 但Around的用处远不止这些,它可以完成其它4个注解的作用
只需要添加Around注解的相应方法这么改就可以了. Around(point())public void methodAround(ProceedingJoinPoint joinPoint){System.out.println(方法执行前);try {joinPoint.proceed();System.out.println(方法执行后);} catch (Throwable e) {System.out.println(方法出现异常);throw new RuntimeException(e);}finally {System.out.println(finally进行增强);}}8. 总结
Spring的AOP基于代理模式实现它使用代理对象Proxy来包装目标对象Target从而实现在目标对象的方法执行前、执行后或抛出异常时插入额外的逻辑。可以通过使用注解或配置文件来定义切面和切点从而将横切关注点应用到目标对象的方法中。
Spring的AOP提供了一系列通知Advice类型如前置通知Before、后置通知After、环绕通知Around、异常通知AfterThrowing和最终通知AfterReturning可以根据需要选择合适的通知类型来实现特定的横切关注点功能。