如何解决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.format
和PrintStream.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 举报,一经查实,本站将立刻删除。