当前位置:   article > 正文

Spring+AspectJ实现的两种方式(注解和xml配置)_spring xml aspect 注解

spring xml aspect 注解

Aop(面向切面编程):

它是一种编程思想,通过Aop将核心业务代码和其他代码(日志、事务等)分离出来,使得代码低耦合,高可用,提高了开发的效率

使用场景:日志记录,性能统计,安全控制,事务处理,异常处理等等

 

百度百科Aop:

 

Aop实现方案:

 

重点讲解第三种方案的实现方式

一:AspectJ强大的表达式:

 

表达式模板:execution(修饰符  返回值  包.类.方法名(参数) throws异常)

  修饰符,一般省略

    public 公共方法

               * 任意

  返回值,不能省略

    void 返回没有值

    String 返回值字符串

    * 任意

  

    com.zby.service  固定包

    com.zby.oa.*.service oa包下面子包 (例如:com.zby.oa.flow.service)

    com.zby.oa..   oa包下面的所有子包(含自己)

    com.zby.oa.*.service.. oa包下面任意子包,固定目录service,service目录任意包

  

    UserServiceImpl 指定类

    *Impl 以Impl结尾

    User* 以User开头

    * 任意

  方法名,不能省略

    addUser 固定方法

    add* 以add开头

    *Do 以Do结尾

    * 任意

  (参数)

    () 无参

    (int) 一个整型

    (int ,int) 两个

    (..) 参数任意

  throws ,可省略,一般不写

 

二:AspectJ支持5种类型的通知注解

 

before:前置通知
   在方法执行前执行


afterReturning:后置通知
           方法正常返回后执行,如果方法中抛出异常,通知无法执行,必须在方法执行后才执行,所以可以获得方法的返回值。

afterThrowing:抛出异常通知
           方法抛出异常后执行,如果方法没有抛出异常,无法执行

after:最终通知
      方法执行完毕后执行,无论方法中是否出现异常

around:环绕通知(很强大,可以直接代替其他四个通知)
           方法执行前后分别执行,可以阻止方法的执行,必须手动执行目标方法
 

 

三:项目导入maven依赖

 

  1. <!-- Spring -->
  2. <dependency>
  3. <groupId>org.springframework</groupId>
  4. <artifactId>spring-context</artifactId>
  5. <version>4.3.12.RELEASE</version>
  6. </dependency>
  7. <!-- AspectJ -->
  8. <dependency>
  9. <groupId>org.springframework</groupId>
  10. <artifactId>spring-aspects</artifactId>
  11. <version>4.3.12.RELEASE</version>
  12. </dependency>
  13. <!-- 单元测试 -->
  14. <dependency>
  15. <groupId>junit</groupId>
  16. <artifactId>junit</artifactId>
  17. <version>4.12</version>
  18. <scope>test</scope>
  19. </dependency>

 

四:基于xml配置实现AspectJ

1:定义UserController

  1. public class UserController {
  2. public int addUser() {
  3. return 1;
  4. }
  5. public int deleteUser() {
  6. return 1;
  7. }
  8. public int updateUser() {
  9. return 1;
  10. }
  11. }

2:定义切面类   实现功能:保存用户操作记录

  1. import org.aspectj.lang.JoinPoint;
  2. import org.aspectj.lang.ProceedingJoinPoint;
  3. public class AopLogging {
  4. // 前置通知
  5. public void before(JoinPoint joinPoint) {
  6. // 获取方法名称
  7. String name = joinPoint.getSignature().getName();
  8. // 获取方法参数
  9. Object[] args = joinPoint.getArgs();
  10. // 实际项目中根据session中的用户信息,保存操作记录到数据库
  11. if (name.equals("add")) {
  12. System.out.println("【用户执行添加操作】");
  13. } else if (name.equals("update")) {
  14. System.out.println("【用户执行更新操作】");
  15. } else {
  16. System.out.println("【用户执行删除操作】");
  17. }
  18. }
  19. // 返回通知 result:方法执行返回的结果
  20. public void afterReturning(JoinPoint joinPoint, Object result) {
  21. // 获取方法名称
  22. String name = joinPoint.getSignature().getName();
  23. // 打印方法执行结果
  24. System.out.println(name + "运行结果:" + result);
  25. }
  26. // 异常通知 exception:方法运行出错时抛出的异常
  27. public void afterThrowing(JoinPoint joinPoint, Exception exception) {
  28. // 获取方法名称
  29. String name = joinPoint.getSignature().getName();
  30. // 打印异常信息
  31. System.out.println(name + "运行异常信息:" + exception);
  32. }
  33. // 最终通知
  34. public void after(JoinPoint joinPoint) {
  35. System.out.println("最终通知");
  36. }
  37. //环绕通知
  38. public Object around(ProceedingJoinPoint joinPoint){
  39. //这里操作相当于前置通知
  40. System.out.println("环绕==前置通知");
  41. Object obj = null;
  42. try {
  43. obj = joinPoint.proceed();
  44. //这里操作是后置通知
  45. System.out.println("环绕==后置通知");
  46. } catch (Throwable e) {
  47. //这里操作是异常通知
  48. System.out.println("环绕==异常通知");
  49. e.printStackTrace();
  50. }
  51. System.out.println("环绕==最终通知");
  52. return obj;
  53. }
  54. }

3:配置xml

  1. <!-- 配置Bean -->
  2. <bean id="userController" class="com.mote.controller.UserController" />
  3. <bean id="aopLogging" class="com.mote.aop.AopLogging" />
  4. <aop:config>
  5. <!-- 配置切入点 -->
  6. <aop:pointcut id="pointcut"
  7. expression="execution(public * com.mote.controller.UserController.*(..)) " />
  8. <!-- 配置切面 -->
  9. <aop:aspect ref="aopLogging">
  10. <!-- 配置相应通知 -->
  11. <aop:before pointcut-ref="pointcut" method="before" />
  12. <!-- result和exception需要和方法中的参数一致 -->
  13. <aop:after-returning pointcut-ref="pointcut" method="afterReturning" returning="result" />
  14. <aop:after-throwing pointcut-ref="pointcut" method="afterThrowing" throwing="exception" />
  15. <aop:after pointcut-ref="pointcut" method="after" />
  16. <aop:around pointcut-ref="pointcut" method="around"/>
  17. </aop:aspect>
  18. </aop:config>

4:测试打印

  1. @Test
  2. public void testXml() {
  3. //创建容器
  4. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
  5. //从容器中获取bean
  6. UserController userController = context.getBean(UserController.class);
  7. //调用方法
  8. userController.deleteUser();
  9. }

 

 

五:纯注解方式实现AspectJ

1:定义UserController,同上

 

2:定义切面类

  1. import org.aspectj.lang.JoinPoint;
  2. import org.aspectj.lang.ProceedingJoinPoint;
  3. import org.aspectj.lang.annotation.After;
  4. import org.aspectj.lang.annotation.AfterReturning;
  5. import org.aspectj.lang.annotation.AfterThrowing;
  6. import org.aspectj.lang.annotation.Around;
  7. import org.aspectj.lang.annotation.Aspect;
  8. import org.aspectj.lang.annotation.Before;
  9. import org.aspectj.lang.annotation.Pointcut;
  10. @Aspect //标注这是一个切面类
  11. public class AopLogging {
  12. //配置公共切点
  13. @Pointcut("execution(public * com.mote.controller.UserController.*(..))")
  14. public void pointcut(){}
  15. @Before("pointcut()")
  16. public void before(JoinPoint joinPoint) {
  17. // 获取方法名称
  18. String name = joinPoint.getSignature().getName();
  19. // 获取方法参数
  20. Object[] args = joinPoint.getArgs();
  21. // 实际项目中根据session中的用户信息,保存操作记录到数据库
  22. if (name.equals("add")) {
  23. System.out.println("【用户执行添加操作】");
  24. } else if (name.equals("update")) {
  25. System.out.println("【用户执行更新操作】");
  26. } else {
  27. System.out.println("【用户执行删除操作】");
  28. }
  29. }
  30. @AfterReturning(pointcut="pointcut()",returning="result")
  31. public void afterReturning(JoinPoint joinPoint, Object result) {
  32. // 获取方法名称
  33. String name = joinPoint.getSignature().getName();
  34. // 打印方法执行结果
  35. System.out.println(name + "运行结果:" + result);
  36. }
  37. @AfterThrowing(pointcut="pointcut()",throwing="exception")
  38. public void afterThrowing(JoinPoint joinPoint, Exception exception) {
  39. // 获取方法名称
  40. String name = joinPoint.getSignature().getName();
  41. // 打印异常信息
  42. System.out.println(name + "运行异常信息:" + exception);
  43. }
  44. @After("pointcut()")
  45. public void after(JoinPoint joinPoint) {
  46. System.out.println("最终通知");
  47. }
  48. @Around("pointcut()")
  49. public Object around(ProceedingJoinPoint joinPoint){
  50. //这里操作相当于前置通知
  51. System.out.println("环绕==前置通知");
  52. Object obj = null;
  53. try {
  54. obj = joinPoint.proceed();
  55. //这里操作相当于后置通知
  56. System.out.println("环绕==后置通知");
  57. } catch (Throwable e) {
  58. //这里操作相当于异常通知
  59. System.out.println("环绕==异常通知");
  60. e.printStackTrace();
  61. }
  62. //这里操作相当于最终通知
  63. System.out.println("环绕==最终通知");
  64. return obj;
  65. }
  66. }

 

 

3:注解配置类

  1. import org.springframework.context.annotation.Bean;
  2. import org.springframework.context.annotation.Configuration;
  3. import org.springframework.context.annotation.EnableAspectJAutoProxy;
  4. import com.mote.aop.AopLogging;
  5. import com.mote.controller.UserController;
  6. @EnableAspectJAutoProxy //开启Spring支持AspectJ注解
  7. @Configuration
  8. public class MainConfig {
  9. @Bean //将UserController添加到spring容器
  10. public UserController userController(){
  11. return new UserController();
  12. }
  13. @Bean //将切面添加到容器
  14. public AopLogging aopLogging(){
  15. return new AopLogging();
  16. }
  17. }

或者使用xml

  1. <!-- 开启Spring支持AspectJ注解 -->
  2. <aop:aspectj-autoproxy/>
  3. <!-- 配置Bean -->
  4. <bean id="userController" class="com.mote.controller.UserController" />
  5. <bean id="aopLogging" class="com.mote.aop.AopLogging" />

 

4:测试打印

1:注解配置类对应的测试方法

  1. @Test
  2. public void test() {
  3. // 创建容器
  4. AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
  5. // 从容器中获取bean
  6. UserController userController = context.getBean(UserController.class);
  7. // 调用方法
  8. userController.deleteUser();
  9. }

2:xml配置对应的测试类

  1. @Test
  2. public void testXml() {
  3. // 创建容器
  4. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
  5. "beans.xml");
  6. // 从容器中获取bean
  7. UserController userController = context.getBean(UserController.class);
  8. // 调用方法
  9. userController.deleteUser();
  10. }

 

注意一:JoinPoint joinPoint在方法的参数列表中,必须放在第一位,否则会报错

注意二:@AfterReturning和@AfterThrowing必须配置对应的returning和throwing参数

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/139170
推荐阅读
相关标签
  

闽ICP备14008679号