Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 子类中自定义注释的Spring AOP切入点表达式_Java_Spring_Aspectj_Spring Aop_Pointcut - Fatal编程技术网

Java 子类中自定义注释的Spring AOP切入点表达式

Java 子类中自定义注释的Spring AOP切入点表达式,java,spring,aspectj,spring-aop,pointcut,Java,Spring,Aspectj,Spring Aop,Pointcut,我正在研究一个日志方面,它需要截取所有用自定义注释注释的类和方法 下面是可以在类和方法上注释的自定义注释类: @Documented @Inherited @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) public @interface Loggable { LogLevel value(); } 我使用这些切入点表达式截取带有注释的方法和类,@Loggable,适

我正在研究一个日志方面,它需要截取所有用自定义注释注释的类和方法

下面是可以在类和方法上注释的自定义注释类:

@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Loggable {
    LogLevel value();
}
我使用这些切入点表达式截取带有注释的方法和类,
@Loggable
适用于所有简单类,但不适用于扩展或实现的类。

//Works for annotation @Loggable on class level
@Pointcut("execution(* *(..)) &&  within(@com.logger.Loggable *)")
public void classAnnotationLogger() {
}

//Working for methods annotated with @Loggable
@Before(value = "@annotation(loggable)", argNames = "jp, loggable")
public void logBeforeAdvice(JoinPoint jp, Loggable loggable) {
  ..
  ..
}
下面是超级类的代码

@Component
@Loggable(LogLevel.INFO)
public abstract class Processor{
  public void process(){
      readProcess();
  }

  public abstract void readProcess();
}
下面是子类的代码

@Service
@Loggable(LogLevel.INFO)
public class MyServiceProcessor extends Processor {

  @Override
  public void readProcess(){
    ...
    ...
  }
}
在应用程序中,通过执行以下操作调用
readProcess()

Processor processor = applicationContext.getBean(MyServiceProcessor.class);
processor.readProcess();
即使我在
处理器上有
@Loggable
MyServiceProcessor
,调用
readProcess
时,也不会调用通知

但是对
process()
调用通知,而不是
readProcess


当注释
@Logabble
应用于任何类或方法时,我如何编写切入点表达式来拦截对任何子类方法的调用

@Pointcut(“执行(**(..))&&in(@com.logger.Loggable*))
public void classAnnotationLogger(){}
它只是一个切入点,而不是一个建议,所以它不会做任何事情,除非你也有一个实际使用这个切入点的建议。你还没有发布这样的建议,所以我只能猜测

第二,您没有提供任何由

@Before(value=“@annotation(loggable)”,argNames=“jp,loggable”)
public void logBeforeAdvice(JoinPoint jp,Loggable Loggable){}
完全没有,即没有带注释的方法。示例代码仅显示带注释的类

至于子类上的
@Loggable
注释,它应该是不必要的,因为它的基类已经携带了相同的注释,并且注释是
@继承的
。这适用于类上的注释,但不适用于方法或接口上的注释,有关说明和可能的解决方法,请参阅

你的这个例子应该是有效的,我看不出有什么理由不起作用:

处理器处理器=applicationContext.getBean(MyServiceProcessor.class); processor.readProcess();
但是对
readProcess()
(相当于
this.readProcess()
)的内部调用将不起作用:

公共作废流程(){
readProcess();
}

这是因为Spring AOP是一个基于代理的“AOP lite”框架,依赖于JDK动态代理(用于接口)或CGLIB代理(用于类)。但是对this.someMethod()
的调用不会通过任何类型的代理路由,因此Spring方面无法拦截它们。这是记录在案的行为。如果您想克服此限制并将方面应用于内部方法调用,请使用完整的AspectJ(如文档所述)。

Hi,感谢您的关注。在我的代码中,我对切入点类AnnotationLogger有一些建议。我知道
这个.someMethod()
不能与标准spring AOP一起工作。这里的问题只是在子类方法中重写的方法readProcess()上进行注释不起作用,但在类级别上进行注释时,会记录process()方法。我是否可以为具有@Loggable注释的重写方法进行日志记录?这里的可能性很小,因为正如我所说的,
@Inherited
,只对类有效,对接口或方法无效。这是JVM/javac限制,而不是AspectJ限制。也许Spring可以在那里发挥一些魔力,但从AspectJ的角度来看,这是行不通的。因此,要么你手动注释你的子类,要么使用APT在编译前添加注释,要么你求助于类级注释加上方法名匹配、注释参数或其他区别因素。我正在使用编译时方面编织来解决这一问题。你能研究一下这个新问题吗[我正面临挑战。我非常感谢大家分享各方面的知识。