2条建议在同一功能上发生冲突

如何解决2条建议在同一功能上发生冲突

嘿, 我开始学习Aspectj,并建立了2个方面。两个方面都有一个匹配相同功能的切入点,并且两个方面都有一个将在该切入点上做些事情的周围建议。 但是,只会“执行”一条建议,我不明白为什么。

让我告诉你:

@Aspect
public class secondAspect {
    @Pointcut("call(  * main.*(..))")
    public void pointCutThatMatchesEveryFunctionFromMain(){

    }
    @Around("pointCutThatMatchesEveryFunctionFromMain()")
    public void adviceOnPointCutThatMatchesEveryFunctionFromMain(JoinPoint jp){
        System.out.println("A method was called");
        System.out.println(jp.getTarget().toString());
    }
}

第二个方面

@Aspect
public class firstAspect {


    @Pointcut("call( public * main.*(..)) && args(x,y)")
    public void pointCutOnMainClassIntArgs(int x,int y) {

    }

    @Pointcut("call( public * main.*(..)) && args(x,y)")
    public void pointCutOnMainClassFloatArgs(float x,float y) {

    }


    @Around("pointCutOnMainClassIntArgs(x,y)")
    public void doSomethingOnThisPointCut(JoinPoint pjp,int x,int y) {
        System.out.println(String.format("The method name is %s and was called with parameteres %d %d",pjp.getTarget().toString(),x,y));
    }


    @Around("pointCutOnMainClassFloatArgs(x,y)")
    public void doSomethingOnThisPointCutWithFloatArgs(JoinPoint pjp,float x,float y) {
        System.out.println(String.format("The method name is %s and was called with parameteres %f %f",y));
    }


}

第一个方面


public class main {
    public static void main(String[] args) {
        main maine = new main();
        maine.calculate(2,3);
        maine.calculate(2.0f,5.0f);
    }
    public void calculate(int x,int y){
        System.out.println(x+y);
    }
    public void calculate(float x,float y){
        System.out.println(x+y);
    }

}

这是我要修改的类。 仅执行secondAspect的adivce。而且我不明白为什么。

解决方法

简短的答案是::将您的建议类型从@Around更改为@Before,然后它会起作用,控制台输出将变为:

A method was called
main@5f341870
The method name is main@5f341870 and was called with parameteres 2 3
The method name is main@5f341870 and was called with parameteres 2,000000 3,000000
5
A method was called
main@5f341870
The method name is main@5f341870 and was called with parameteres 2,000000 5,000000
7.0

注意事项:如果您检查以上日志输出,您会发现建议doSomethingOnThisPointCutWithFloatArgs也与带有int参数的方法匹配,这可能不是您的意图。在切入点中,您需要比main.*(..)更精确,并且最好使用main.*(int,int)main.*(float,float)

长答案是:您应该阅读AspectJ教程。例如,@Around个建议需要

  • 一个ProoceedingJoinPoint方法参数,而不是简单的JoinPoint
  • 显式调用联接点的proceed()方法,以实际调用截获的目标方法。您没有这样做,这是仅执行一个随机方面(AspectJ发现的第一个方面)的解释,而没有执行第二个方面的解释,是因为您以从未进行目标方法的方式设计了建议代码。 / li>
  • 如果要匹配返回Object以外的内容的方法,则返回void或更具体的非void类型。您要么需要返回proceed()的结果,要么希望将其作为目标方法的结果返回。

更多建议:

  • 请遵循Java编码准则,并且请勿以小写字母开头类或方面名称。
  • 具体不要使用类名main,而不要使用方法main,并且由于命名冲突,局部变量maine不会使用。我想它不会比这更丑。
  • 当您打印System.out.println(jp.getTarget().toString())之类的对象时,toString()是多余的,因为在打印对象时始终会隐式调用此方法。
  • 如果您有多个面向相同联接点的方面并希望强制执行调用它们的特定顺序,请学习如何使用@DeclarePrecedence
  • 我建议摆脱单独的@Pointcut定义,并内联定义切入点,除非您希望重复使用切入​​点。
  • 如果您想知道AspectJ中发生了什么,为什么不打印完整的联接点而不是“调用方法”?它有助于了解正在发生的事情。
  • 了解call()execution()之间的语义区别:前者拦截所有调用方(即方法调用的源),而后者则拦截调用本身,无论它们来自何处。有关更多信息,请参见here和AspectJ手册。
  • 尝试避免将您的类和方面放入默认包中。这不是很好的风格。您还将注意到AspectJ切入点对包名称可能非常敏感。
  • 使用PrintStream.println代替合并String.formatPrintStream.printf

怎么样?

package de.scrum_master.app;

public class Application {
  public static void main(String[] args) {
    Application application = new Application();
    application.calculate(2,3);
    application.calculate(2.0f,5.0f);
  }

  public void calculate(int x,int y) {
    System.out.println(x + y);
  }

  public void calculate(float x,float y) {
    System.out.println(x + y);
  }
}
package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class FirstAspect {
  @Before("execution(public !static * *(int,int)) && args(x,y) && target(targetInstance)")
  public void publicNonStaticMethodsWith2IntParameters(JoinPoint joinPoint,int x,int y,Object targetInstance) {
    System.out.printf("[FA] %s -> %s [%s,%s]%n",joinPoint,targetInstance,x,y);
  }

  @Before("execution(public !static * *(float,float)) && args(x,y) && target(targetInstance)")
  public void publicNonStaticMethodsWith2FloatParameters(JoinPoint joinPoint,float x,float y,y);
  }
}
package de.scrum_master.aspect;
import java.util.Arrays;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class SecondAspect {
  @Before("execution(public !static * *(..)) && target(targetInstance)")
  public void publicNonStaticMethods(JoinPoint joinPoint,Object targetInstance) {
    System.out.printf("[SA] %s -> %s %s%n",Arrays.deepToString(joinPoint.getArgs()));
  }
}
[FA] execution(void de.scrum_master.app.Application.calculate(int,int)) -> de.scrum_master.app.Application@6c3708b3 [2,3]
[SA] execution(void de.scrum_master.app.Application.calculate(int,3]
5
[SA] execution(void de.scrum_master.app.Application.calculate(float,float)) -> de.scrum_master.app.Application@6c3708b3 [2.0,5.0]
[FA] execution(void de.scrum_master.app.Application.calculate(float,5.0]
7.0

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-