12_Spring_AOP注解方式实现_掌握

12_Spring_AOP注解方式实现_掌握

AspectJ本身并不是spring框架中的组成部分,
是一个独立的AOP框架,一般把AspectJ和Spring框架的AOP依赖一起使用,所以要导入一个独立的依赖

实现的两种方式

1 基于注解方式实现 (熟练)

2 基于XML配置方式 (了解)

准备工作1

导入依赖

  1. org.springframework
  2. spring-context
  3. 5.3.5
  4. org.springframework
  5. spring-aspects
  6. 5.3.5
  7. <!--
  8. org.aspectj
  9. aspectjweaver
  10. 1.9.6
  11. -->
  12. aopalliance
  13. aopalliance
  14. 1.0
  15. commons-logging
  16. commons-logging
  17. 1.2
  18. com.alibaba
  19. druid
  20. 1.1.10
  21. mysql
  22. mysql-connector-java
  23. 8.0.22
  24. junit
  25. junit
  26. 4.13.1
  27. test
  28. org.projectlombok
  29. lombok
  30. 1.18.12
  31. provided

准备工作2

切入点表达式: 通过一个表达式来确定AOP要增强的是哪个或者那些方法

语法结构:execution([权限修饰符][返回值类型][类的全路径名][方法名](参数 列表) )

例子1

execution(* com.msb.dao.UserDaoImpl.add(..))  //指定切点为UserDaoImpl.add方法

execution(* com.msb.dao.UserDaoImpl.*(..))      //指定切点为UserDaoImpl.所有的方法

execution(* com.msb.dao..(..))                        
//指定切点为dao包下所有的类中的所有的方法

execution(* com.msb.dao.*.add(..))                     //
指定切点为dao包下所有的类中的add的方法

execution(* com.msb.dao..add(..))                   //
指定切点为dao包下所有的类中的add开头的方法

image

基于注解方式实现

项目结构

image
开启注解扫描和AOP切面编程自动生成代理对象配置

  1. <beans xmlns="http://www.springframework.org/schema/beans"
  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns:p="http://www.springframework.org/schema/p"
  4. xmlns:c="http://www.springframework.org/schema/c"
  5. xmlns:util="http://www.springframework.org/schema/util"
  6. xmlns:context="http://www.springframework.org/schema/context"
  7. xmlns:aop="http://www.springframework.org/schema/aop"
  8. xsi:schemaLocation="
  9. http://www.springframework.org/schema/beans
  10. http://www.springframework.org/schema/beans/spring-beans.xsd
  11. http://www.springframework.org/schema/util
  12. http://www.springframework.org/schema/util/spring-util.xsd
  13. http://www.springframework.org/schema/context
  14. http://www.springframework.org/schema/context/spring-context.xsd
  15. http://www.springframework.org/schema/aop
  16. http://www.springframework.org/schema/aop/spring-aop.xsd
  17. ">
  18. <context:component-scan base-package="com.msb"/>
  19. aop:aspectj-autoproxy/

准备接口

UserDao和EmpDao

  1. package com.msb.dao;

  2. /**

    • @Author: Ma HaiYang
    • @Description: MircoMessage:Mark_7001
  3. */

  4. public interface EmpDao {

  5. int addEmp(Integer empno,String ename,String job);

  6. }

  7. package com.msb.dao;

  8. /**

    • @Author: Ma HaiYang
    • @Description: MircoMessage:Mark_7001
  9. */

  10. public interface UserDao {

  11. int addUser(Integer userid,String username);

  12. }

接口实现类

  1. package com.msb.dao.impl;

  2. import com.msb.dao.UserDao;

  3. import org.springframework.stereotype.Repository;

  4. /**

    • @Author: Ma HaiYang
    • @Description: MircoMessage:Mark_7001
  5. */

  6. @Repository

  7. public class UserDaoImpl implements UserDao {

  8. public int addUser(Integer userid,String username){

  9. System.out.println("userdao add ... ...");

  10. //int i =1/0;

  11. return 1;

  12. }

  13. }

  14. package com.msb.dao.impl;

  15. import com.msb.dao.EmpDao;

  16. import com.msb.dao.UserDao;

  17. import org.springframework.stereotype.Repository;

  18. /**

    • @Author: Ma HaiYang
    • @Description: MircoMessage:Mark_7001
  19. */

  20. @Repository

  21. public class EmpDaoImpl implements EmpDao {

  22. public int addEmp(Integer empno,String ename,String job){

  23. System.out.println("empDao add ... ...");

  24. return 1;

  25. }

  26. }

准备切面

  1. package com.msb.aspect;
  2. import org.aspectj.lang.JoinPoint;
  3. import org.aspectj.lang.ProceedingJoinPoint;
  4. import org.aspectj.lang.annotation.*;
  5. import org.springframework.core.annotation.Order;
  6. import org.springframework.stereotype.Component;
  7. import java.util.Arrays;
  8. /**
    • @Author: Ma HaiYang
    • @Description: MircoMessage:Mark_7001
  9. */
  10. @Component
  11. @Aspect
  12. public class DaoAspect {
  13. //定义公共切点
  14. @Pointcut("execution(* com.msb.dao..add(..))")
  15. public void addPointCut(){}
  16. /*
  17. * 前置通知: 切点方法执行之前先执行的功能
  18. * 参数列表可以用JoinPoint接收切点对象
  19. * 可以获取方法执行的参数
  20. * */
  21. @Before("addPointCut()")
  22. public void methodBefore(JoinPoint joinPoint){
  23. System.out.println("Before invoked");
  24. }
  25. /*
  26. * 后置通知:方法执行之后要增强的功能
  27. * 无论切点方法是否出现异常都会执行的方法
  28. * 参数列表可以用JoinPoint接收切点对象
  29. * */
  30. @After("addPointCut()")
  31. public void methodAfter(JoinPoint joinPoint){
  32. System.out.println("After invoked");
  33. }
  34. /*
  35. * 返回通知:切点方法正常运行结束后增强的功能
  36. * 如果方法运行过程中出现异常,则该功能不运行
  37. * 参数列表可以用 JoinPoint joinPoint接收切点对象
  38. * 可以用Object res接收方法返回值,需要用returning指定返回值名称
  39. * */
  40. @AfterReturning( value = "addPointCut()",returning = "res")
  41. public void methodAfterReturning(JoinPoint joinPoint,Object res){
  42. System.out.println("AfterReturning invoked");
  43. }
  44. /*
  45. * 异常通知:切点方法出现异常时运行的增强功能
  46. * 如果方法运行没有出现异常,则该功能不运行
  47. * 参数列表可以用Exception ex接收异常对象 需要通过throwing指定异常名称
  48. * */
  49. @AfterThrowing( value = "addPointCut()",throwing = "ex")
  50. public void methodAfterThrowing(Exception ex){
  51. System.out.println("AfterThrowing invoked");
  52. }
  53. /*环绕通知:在切点方法之前和之后都进行功能的增强
  54. * 需要在通知中定义方法执行的位置,并在执行位置之前和之后自定义增强的功能
  55. * 方法列表可以通过ProceedingJoinPoint获取执行的切点
  56. * 通过proceedingJoinPoint.proceed()方法控制切点方法的执行位置
  57. * proceedingJoinPoint.proceed()方法会将切点方法的返回值获取到,并交给我们,可以做后续处理
  58. * 我们在环绕通知的最后需要将切点方法的返回值继续向上返回,否则切点方法在执行时接收不到返回值
  59. * */
  60. @Around("addPointCut()")
  61. public Object methodAround(ProceedingJoinPoint proceedingJoinPoint)
    throws Throwable {
  62. System.out.println("aroundA invoked");
  63. Object proceed = proceedingJoinPoint.proceed();
  64. System.out.println("aroundB invoked");
  65. return proceed;
  66. }
  67. }

测试代码

  1. @Test
  2. public void test1(){
  3. ApplicationContext context=new
    ClassPathXmlApplicationContext("applicationContext.xml");
  4. UserDao userDao = context.getBean( UserDao.class);
  5. int add = userDao.addUser(10,"晓明");
  6. }

image

image

有多个增强类对同一个方法进行增强,通过@Order注解设置增强类优先级

数字越小,优先级越高

数字越小,其代理位置越靠近注入位置

image

image

完全使用注解开发

创建配置类

  1. package com.msb.config;
  2. import org.springframework.context.annotation.ComponentScan;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.context.annotation.EnableAspectJAutoProxy;
  5. /**
    • @Author: Ma HaiYang
    • @Description: MircoMessage:Mark_7001
  6. */
  7. @Configuration
  8. @ComponentScan(basePackages = "com.msb")
  9. @EnableAspectJAutoProxy(proxyTargetClass = true)
  10. public class SpringConfig {
  11. }

测试代码

  1. @Test
  2. public void test2(){
  3. ApplicationContext context=new
    AnnotationConfigApplicationContext(SpringConfig.class);
  4. UserDao userDao = context.getBean( UserDao.class);
  5. int add = userDao.addUser(10,"晓明");
  6. }

Generated with Mybase Desktop 8.2.13

posted @ 2023-07-30 12:39  AidenDong  阅读(43)  评论(0)    收藏  举报