Spring基础(十一):AOP注解和XML方式实现

举报
Lansonli 发表于 2022/09/25 00:23:51 2022/09/25
【摘要】 文章目录 AOP注解和XML方式实现 一、注解方式实现 1、准备工作 2、准备接口 3、接口实现类 4、准备切面 5、测试代码 6、概念补充 7、完全使用注解开发 二、XML配置方式实现 1、创建两个类,增强类和被增强类,创建方法 2、在spring配置文件中创建两个类对象 3、在spring配置文件中配置...

文章目录

AOP注解和XML方式实现

一、注解方式实现

1、准备工作

2、准备接口

3、接口实现类

4、准备切面

5、测试代码

6、概念补充

7、完全使用注解开发

二、XML配置方式实现

1、创建两个类,增强类和被增强类,创建方法

2、在spring配置文件中创建两个类对象

3、在spring配置文件中配置切入点


AOP注解和XML方式实现

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

实现的两种方式

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

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

一、注解方式实现

1、准备工作

导入依赖


  
  1. <dependencies>
  2. <!--spring核心容器包-->
  3. <dependency>
  4. <groupId>org.springframework</groupId>
  5. <artifactId>spring-context</artifactId>
  6. <version>5.3.5</version>
  7. </dependency>
  8. <!--spring切面包-->
  9. <dependency>
  10. <groupId>org.springframework</groupId>
  11. <artifactId>spring-aspects</artifactId>
  12. <version>5.3.5</version>
  13. </dependency>
  14. <!--织入包 spring-aspects 已经导入该包,这里可以不导入-->
  15. <!--<dependency>
  16. <groupId>org.aspectj</groupId>
  17. <artifactId>aspectjweaver</artifactId>
  18. <version>1.9.6</version>
  19. </dependency>-->
  20. <!--aop联盟包-->
  21. <dependency>
  22. <groupId>aopalliance</groupId>
  23. <artifactId>aopalliance</artifactId>
  24. <version>1.0</version>
  25. </dependency>
  26. <!--Apache Commons日志包-->
  27. <dependency>
  28. <groupId>commons-logging</groupId>
  29. <artifactId>commons-logging</artifactId>
  30. <version>1.2</version>
  31. </dependency>
  32. <!--德鲁伊连接池-->
  33. <dependency>
  34. <groupId>com.alibaba</groupId>
  35. <artifactId>druid</artifactId>
  36. <version>1.1.10</version>
  37. </dependency>
  38. <!--mysql驱动-->
  39. <dependency>
  40. <groupId>mysql</groupId>
  41. <artifactId>mysql-connector-java</artifactId>
  42. <version>8.0.22</version>
  43. </dependency>
  44. <!--Junit单元测试-->
  45. <dependency>
  46. <groupId>junit</groupId>
  47. <artifactId>junit</artifactId>
  48. <version>4.13.1</version>
  49. <scope>test</scope>
  50. </dependency>
  51. <!--lombok -->
  52. <dependency>
  53. <groupId>org.projectlombok</groupId>
  54. <artifactId>lombok</artifactId>
  55. <version>1.18.12</version>
  56. <scope>provided</scope>
  57. </dependency>
  58. </dependencies>

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

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

例子1


  
  1. execution(* com.lanson.dao.UserDaoImpl.add(..))  //指定切点为UserDaoImpl.add方法 
  2. execution(* com.lanson.dao.UserDaoImpl.*(..))      //指定切点为UserDaoImpl.所有的方法 
  3. execution(* com.lanson.dao.*.*(..))                         //指定切点为dao包下所有的类中的所有的方法 
  4. execution(* com.lanson.dao.*.add(..))                     // 指定切点为dao包下所有的类中的add的方法 
  5. execution(* com.lanson.dao.*.add*(..))                   // 指定切点为dao包下所有的类中的add开头的方法 

基于注解方式实现

项目结构

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


  
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:p="http://www.springframework.org/schema/p"
  5. xmlns:c="http://www.springframework.org/schema/c"
  6. xmlns:util="http://www.springframework.org/schema/util"
  7. xmlns:context="http://www.springframework.org/schema/context"
  8. xmlns:aop="http://www.springframework.org/schema/aop"
  9. xsi:schemaLocation="
  10. http://www.springframework.org/schema/beans
  11. http://www.springframework.org/schema/beans/spring-beans.xsd
  12. http://www.springframework.org/schema/util
  13. http://www.springframework.org/schema/util/spring-util.xsd
  14. http://www.springframework.org/schema/context
  15. http://www.springframework.org/schema/context/spring-context.xsd
  16. http://www.springframework.org/schema/aop
  17. http://www.springframework.org/schema/aop/spring-aop.xsd
  18. ">
  19. <!--spring 包扫描 -->
  20. <context:component-scan base-package="com.lanson"/>
  21. <!--aop autoProxy 自动生成代理对象 -->
  22. <aop:aspectj-autoproxy/>
  23. </beans>

2、准备接口

UserDao和EmpDao


  
  1. package com.lanson.dao;
  2. /**
  3. * @Author: Lansonli
  4. * @Description: MircoMessage:Mark_7001
  5. */
  6. public interface EmpDao {
  7. int addEmp(Integer empno,String ename,String job);
  8. }

  
  1. package com.lanson.dao;
  2. /**
  3. * @Author: Lansonli
  4. * @Description: MircoMessage:Mark_7001
  5. */
  6. public interface UserDao {
  7. int addUser(Integer userid,String username);
  8. }

3、接口实现类


  
  1. package com.lanson.dao.impl;
  2. import com.lanson.dao.UserDao;
  3. import org.springframework.stereotype.Repository;
  4. /**
  5. * @Author: Lansonli
  6. * @Description: MircoMessage:Mark_7001
  7. */
  8. @Repository
  9. public class UserDaoImpl implements UserDao {
  10. public int addUser(Integer userid,String username){
  11. System.out.println("userdao add ... ...");
  12. //int i =1/0;
  13. return 1;
  14. }
  15. }

  
  1. package com.lanson.dao.impl;
  2. import com.lanson.dao.EmpDao;
  3. import com.lanson.dao.UserDao;
  4. import org.springframework.stereotype.Repository;
  5. /**
  6. * @Author: Lansonli
  7. * @Description: MircoMessage:Mark_7001
  8. */
  9. @Repository
  10. public class EmpDaoImpl implements EmpDao {
  11. public int addEmp(Integer empno,String ename,String job){
  12. System.out.println("empDao add ... ...");
  13. return 1;
  14. }
  15. }

4、准备切面


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

5、测试代码


  
  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. }

6、概念补充

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

数字越小,优先级越高

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

7、完全使用注解开发

创建配置类


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

测试代码


  
  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. }

二、XML配置方式实现

1、创建两个类,增强类和被增强类,创建方法

见上面的代码

2、在spring配置文件中创建两个类对象


  
  1. <!--创建对象-->
  2. <bean id="userDao" class="com.com.lanson.UserDaoImpl"></bean>
  3. <bean id="daoAspect" class="com.com.aspect.DaoAspect"></bean>

3、在spring配置文件中配置切入点


  
  1. <!--配置aop增强-->
  2. <aop:config>
  3. <!--切入点-->
  4. <aop:pointcut id="pointCutAdd" expression="execution(* com.lanson.dao.UserDao.add*(..))"/>
  5. <!--配置切面-->
  6. <aop:aspect ref="daoAspect">
  7. <!--增强作用在具体的方法上-->
  8. <aop:before method="methodBefore" pointcut-ref="pointCutAdd"/>
  9. <aop:after method="methodAfter" pointcut-ref="pointCutAdd"/>
  10. <aop:around method="methodAround" pointcut-ref="pointCutAdd"/>
  11. <aop:after-returning method="methodAfterReturning" pointcut-ref="pointCutAdd" returning="res"/>
  12. <aop:after-throwing method="methodAfterThrowing" pointcut-ref="pointCutAdd" throwing="ex"/>
  13. </aop:aspect>
  14. </aop:config>

  • 📢博客主页:https://lansonli.blog.csdn.net
  • 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
  • 📢本文由 Lansonli 原创,首发于 CSDN博客🙉
  • 📢停下休息的时候不要忘了别人还在奔跑,希望大家抓紧时间学习,全力奔赴更美好的生活✨

文章来源: lansonli.blog.csdn.net,作者:Lansonli,版权归原作者所有,如需转载,请联系作者。

原文链接:lansonli.blog.csdn.net/article/details/126810766

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。