Spring--9.aop操作

本文介绍了如何使用AspectJ在Spring框架中实现面向切面编程(AOP)。详细讲解了AspectJ的两种集成方式:基于XML配置和基于注解的方式,并深入探讨了五种通知类型及其应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1       概述

1.1  aspectj

1 在spring里面进行aop操作,使用aspectj实现

(1)aspectj不是spring一部分,和spring一起使用进行aop操作

(2)Spring2.0以后新增了对AspectJ支持

 

1.2  两种方式

2 使用aspectj实现aop有两种方式(重点)

(1)基于aspectj的xml配置

(2)基于aspectj的注解方式

 

 

 

2       Aop操作准备—aspect

2.1  导包

1 除了导入基本的jar包之外,还需要导入aop相关的jar包

 

2.2  引入约束

2 创建spring核心配置文件,导入aop的约束

 

 

3       增强类

          被加强的方法所在的类叫被增强类

 

3.1  切入点表达式

1 切入点:实际增强的方法

 

2 常用的表达式

execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)

(1)execution(*  spring.aop.Book.add(..))

(2)execution(* spring.aop.Book.*(..))

(3)execution(* *.*(..))

(4) 匹配所有save开头的方法 execution(* save*(..))

 

3. 切入点表达式操作符 &&, ||, !

 

       在 AspectJ 切面中, 可以通过 @Pointcut 注解将一个切入点声明成简单的方法. 切入点的方法体通常是空的

 

3.2  五种通知

 

3.2.1   前置通知-- JoinPoint访问连接点

       前置通知:在方法执行之前执行的通知;   前置通知使用 @Before 注解, 并将切入点表达式的值作为注解值.

       可以在通知方法中声明一个类型为 JoinPoint 的参数. 然后就能访问链接细节. 如方法名称和参数值.

//声明该方法是一个前置通知:在目标方法开始前执行
    @Before("execution(publicint spring.aop.impl.*.*(int , int))")
    public void beforeMethod(JoinPoint joinPoint){
       String methodName = joinPoint.getSignature().getName();
       List<Object> args = Arrays.asList(joinPoint.getArgs());
      
       System.out.println("此方法 "+ methodName +" 开始:" + args);
    }

3.2.2   后置通知-- JoinPoint

       后置通知是在连接点完成之后执行的, 即连接点返回结果或者抛出异常的时候, 下面的后置通知记录了方法的终止.

       一个切面可以包括一个或者多个通知.

//后置通知:在目标方法开始后执行(无论是否发生异常),其不能访问控制结果
    @After("execution(publicint spring.aop.impl.*.*(int , int))")
    public void afterMethod(JoinPoint joinPoint){
       String methodName = joinPoint.getSignature().getName();
          
       System.out.println("此方法 "+ methodName +" 结束");
    } 

3.2.3   返回通知—JoinPoint,result访问连接点的返回值

       在返回通知中, 只要将 returning 属性添加到 @AfterReturning 注解中, 就可以访问连接点的返回值. 该属性的值即为用来传入返回值的参数名称.

       必须在通知方法的签名中添加一个同名参数. 在运行时, Spring AOP 会通过这个参数传递返回值.

       原始的切点表达式需要出现在 pointcut 属性中

//返回通知:在目标方法开始后执行,是可以访问到方法的返回值的
    @AfterReturning(value = "execution(publicint spring.aop.impl.*.*(int , int))" ,    returning = "result")
    public void afterReturning(JoinPoint joinPoint , Object result){
       String methodName = joinPoint.getSignature().getName();
             
       System.out.println("此方法 "+ methodName +" 结果: " + result);
    }  

3.2.4   异常通知—JoinPoint,Exception

       只在连接点抛出异常时才执行异常通知

       将 throwing 属性添加到 @AfterThrowing 注解中, 也可以访问连接点抛出的异常. Throwable 是所有错误和异常类的超类. 所以在异常通知方法可以捕获到任何错误和异常.

//异常通知:在目标方法异常后执行;是可以访问到  异常对象
    @AfterThrowing(value = "execution(publicint spring.aop.impl.*.*(int , int))" ,throwing = "e")
    public void afterThrowing(JoinPoint joinPoint , Exception e){
       String methodName = joinPoint.getSignature().getName();
                 
       System.out.println("此方法 "+ methodName +" 异常: " + e);
    }   

3.2.5   环绕通知—ProceedingJoinPoint连接点

       环绕通知相当于前面四种的一个概括

对于环绕通知来说, 连接点的参数类型必须是 ProceedingJoinPoint ,其中proceed() 方法来执行被代理的方法. 如果忘记这样做就会导致通知被执行了, 但目标方法没有被执行.

       注意: 环绕通知的方法需要返回目标方法执行之后的结果, 即调用 joinPoint.proceed(); 的返回值, 否则会出现空指针异常

//把这个类声明为一个对象:需要把该类放入 IOC 容器中,再声明一个切面
@Aspect
@Component
public class Logging {
    /**
     * 环绕通知:相当于前四种通知的集合
     * 需要携带ProceedingJoinPoint 类型参数
     * 类似动态代理的全过程,ProceedingJoinPoint类型参数可以决定是否执行目标方法,且要有返回值
     */
    @Around("execution(publicint spring.aop.impl.*.*(int , int))")
    public Object aroundMethod(ProceedingJoinPoint pjp){
       Object result = null;
      
       String methodName = pjp.getSignature().getName();
       List<Object> args = Arrays.asList(pjp.getArgs());
      
       try {
           //前置通知
           System.out.println("前置通知此方法 "+ methodName +" 开始:" + args);
           //执行方法
           result = pjp.proceed();
           //返回通知
           System.out.println("返回通知此方法 "+ methodName +" 结果: " + result);
       } catch (Throwable e) {
           //异常通知
           System.out.println("异常通知此方法 "+ methodName +" 异常: " + e);
           throw new RuntimeException(e);
       }
       //后置通知
       System.out.println("后置通知此方法 "+ methodName +" 结束");
       return result;
    }
} 

3.3  切面优先级

  

4       Aspectj的aop操作(xml配置)

4.1  增强类

 

4.2  XML配置

4.2.1   配置

  

4.2.2   配置切入点

切入点使用<aop:pointcut> 元素声明

切入点必须定义在 <aop:aspect> 元素下, 或者直接定义在<aop:config> 元素下.

定义在 <aop:aspect> 元素下: 只对当前切面有效

定义在 <aop:config> 元素下: 对所有切面都有效

基于 XML 的 AOP 配置不允许在切入点表达式中用名称引用其他切入点.

 

4.2.3   配置切面—引入增强对象

       当使用 XML 声明切面时, 需要在 <beans> 根元素中导入 aop Schema

       在 Bean 配置文件中, 所有的 Spring AOP 配置都必须定义在 <aop:config> 元素内部. 对于每个切面而言, 都要创建一个<aop:aspect> 元素来为具体的切面实现引用后端 Bean 实例.

       切面 Bean 必须有一个标示符, 供 <aop:aspect> 元素引用

4.2.4   配置通知—引入切入点

       在 aop Schema 中, 每种通知类型都对应一个特定的 XML 元素.

       通知元素需要使用 <pointcut-ref> 来引用切入点, 或用 <pointcut> 直接嵌入切入点表达式.  method 属性指定切面类中通知方法的名称.

 

<!-- 1.创建对象 -->
   <bean id="book" class="spring.aop.Book"></bean>
   <bean id="myBook" class="spring.aop.MyBook"></bean>
  
   <!-- 2.配置aop操作 -->
   <aop:config>
      <!-- 2.1配置切入点 -->
      <aop:pointcut expression="execution(* spring.aop.Book.*(..))"id="pointcut1"/>
      <!-- 2.2配置切面  把增强用到方法上面-->
      <aop:aspect ref="myBook">
         <!-- 配置增强类型  method:增强类里面使用哪个方法作为前置-->
         <aop:before method="before1" pointcut-ref="pointcut1"/>
         <aop:after-returning method="after1" pointcut-ref="pointcut1"/>
        
         <aop:around method="around1" pointcut-ref="pointcut1"/>
      </aop:aspect>
   </aop:config> 

5       aop操作(注解)

5.1  XML

第一步 创建对象

第二步 在spring核心配置文件中,开启aop操作

 

 

5.2  增强类注解

第三步 在增强类上面使用注解完成aop操作

 


org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name &#39;org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat&#39;: Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: error Type referred to is not an annotation type: com$ycxw$annotation$MyLog at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:165) ~[spring-boot-2.7.13.jar:2.7.13] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:577) ~[spring-context-5.3.28.jar:5.3.28] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.13.jar:2.7.13] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:731) [spring-boot-2.7.13.jar:2.7.13] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) [spring-boot-2.7.13.jar:2.7.13] at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) [spring-boot-2.7.13.jar:2.7.13] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303) [spring-boot-2.7.13.jar:2.7.13] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292) [spring-boot-2.7.13.jar:2.7.13] at com.hzb.ServerApplication.main(ServerApplication.java:10) [classes/:na] Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name &#39;org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat&#39;: Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: error Type referred to is not an annotation type: com$ycxw$annotation$MyLog at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:628) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:410) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:213) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getWebServerFactory(ServletWebServerApplicationContext.java:219) ~[spring-boot-2.7.13.jar:2.7.13] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:182) ~[spring-boot-2.7.13.jar:2.7.13] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:162) ~[spring-boot-2.7.13.jar:2.7.13] ... 8 common frames omitted Caused by: java.lang.IllegalArgumentException: error Type referred to is not an annotation type: com$ycxw$annotation$MyLog at org.aspectj.weaver.tools.PointcutParser.parsePointcutExpression(PointcutParser.java:319) ~[aspectjweaver-1.9.7.jar:na] at org.springframework.aop.aspectj.AspectJExpressionPointcut.buildPointcutExpression(AspectJExpressionPointcut.java:227) ~[spring-aop-5.3.28.jar:5.3.28] at org.springframework.aop.aspectj.AspectJExpressionPointcut.obtainPointcutExpression(AspectJExpressionPointcut.java:198) ~[spring-aop-5.3.28.jar:5.3.28] at org.springframework.aop.aspectj.AspectJExpressionPointcut.getClassFilter(AspectJExpressionPointcut.java:177) ~[spring-aop-5.3.28.jar:5.3.28] at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:226) ~[spring-aop-5.3.28.jar:5.3.28] at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:289) ~[spring-aop-5.3.28.jar:5.3.28] at org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(AopUtils.java:321) ~[spring-aop-5.3.28.jar:5.3.28] at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply(AbstractAdvisorAutoProxyCreator.java:128) ~[spring-aop-5.3.28.jar:5.3.28] at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:97) ~[spring-aop-5.3.28.jar:5.3.28] at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:78) ~[spring-aop-5.3.28.jar:5.3.28] at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:341) ~[spring-aop-5.3.28.jar:5.3.28] at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:293) ~[spring-aop-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:455) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1808) ~[spring-beans-5.3.28.jar:5.3.28] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) ~[spring-beans-5.3.28.jar:5.3.28] ... 25 common frames omitted
最新发布
06-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值