Java 在另一个方法内的方法调用后执行某些操作
我想在调用非公共方法(bar)后执行一些特定操作。此方法在另一个方法(foo)中调用。请注意,“bar”和“foo”都是在第三方jar文件中定义的 我试图在使用spring的面向方面编程中使用Java 在另一个方法内的方法调用后执行某些操作,java,spring,aop,aspectj,Java,Spring,Aop,Aspectj,我想在调用非公共方法(bar)后执行一些特定操作。此方法在另一个方法(foo)中调用。请注意,“bar”和“foo”都是在第三方jar文件中定义的 我试图在使用spring的面向方面编程中使用@之前的注释来实现这一点 在调用jar文件中的特定函数之后,有人能告诉我如何做特定的事情(调用特定函数)吗?避免使用Spring AOP。它不允许这样做,因为Spring创建了一个代理来对bean进行体化,因此,只有对“代理”的调用才会被体化。这意味着,如果你有一个第三方类的bean(我们称之为fooBea
@之前的注释来实现这一点
在调用jar文件中的特定函数之后,有人能告诉我如何做特定的事情(调用特定函数)吗?避免使用Spring AOP。它不允许这样做,因为Spring创建了一个代理来对bean进行体化,因此,只有对“代理”的调用才会被体化。这意味着,如果你有一个第三方类的bean(我们称之为fooBean),当你执行fooBean.foo()
时,你实际上正在通过一个具有方面逻辑的代理,但是一旦执行foo()
方法,那么内部调用,例如对bar()
的调用将不再被认为是该代理,所以,那里没有相位
Mybe运行到一个更复杂的解决方案中,因为使用pure可能会对您有所帮助,因为它不是基于proxys的,它只是增强了编译的字节码,避免使用Spring AOP。它不允许这样做,因为Spring创建了一个代理来对bean进行体化,因此,只有对“代理”的调用才会被体化。这意味着,如果你有一个第三方类的bean(我们称之为fooBean),当你执行fooBean.foo()
时,你实际上正在通过一个具有方面逻辑的代理,但是一旦执行foo()
方法,那么内部调用,例如对bar()
的调用将不再被认为是该代理,所以,那里没有相位
Mybe遇到了一个更复杂的解决方案,因为使用pure可能会对您有所帮助,因为它不是基于proxys的,它只是增强了编译的字节码,正如Gervasio Amy所建议的,您需要使用AspectJ,而不是Spring AOP。如果您在一个Spring环境中,您可以使用SpringAOP来代替它,这是没有问题的。如果您还没有使用Spring,AOP不是开始使用它的理由,AspectJ在没有Spring的简单JavaSE(或EE)版本中工作
您需要做的是:
- 使用AspectJ编译器ajc编译方面代码。(您也可以使用它编译整个应用程序,因为它也是Java编译器javac的替代品。)
- 创建加载时编织配置aop.xml,以便使应用程序能够在类加载期间动态地将方面代码编织到第三方库中。我让你来决定怎么做,只要检查一下
- 通过
-javaagent:/path/to/aspectjweaver.jar
开关在命令行上使用AspectJ编织代理启动JVM或应用程序服务器
现在你想要什么样的外观?让我们尝试一些变体并优化切入点,以使其匹配。但是,首先让我们为我们的实验搭建一个平台,使用一些示例第三方类(Foo
和Bar
)和一个小的驱动程序应用程序(application
):
示例应用程序和第三方代码:
包my.thirdparty.application;
公共类酒吧{
Foo-Foo=新的Foo();
公共无效剂量测定法(){
somethod();
bar();
anotherMethod();
}
私有方法(){
foo.blah();
foo.foo();
foo.zot();
}
专用空格键(){
foo.blah();
//这是我们要截获的唯一一个调用,由“bar”调用的“foo”
foo.foo();
foo.zot();
anotherMethod();
}
私有void anotherMethod(){
foo.blah();
foo.foo();
foo.zot();
}
}
package de.scrum\u master.app;
导入my.thirdparty.application.Bar;
公共类应用程序{
公共静态void main(字符串[]args){
新条().doSomething();
}
}
如您所见,Application.main
创建一个Bar
对象并调用一个公共方法Bar.doSomething
。此方法会触发一系列其他方法调用,其中一些方法最终被间接调用为Foo.Foo
,但只有一个直接调用从Bar.Bar
到Foo.Foo
(根据您的问题,这是我们感兴趣的)
方面,第1部分:拦截对Foo.Foo的所有调用
package de.scrum\u master.aspect;
导入my.thirdparty.application.Foo;
导入my.thirdparty.application.Bar;
公共方面拦截器{
切入点所有调用():
调用(*Foo.Foo(..);
对象周围(foooobject):allCalls()&&target(foooobject){
System.out.println(thisJoinPointStaticPart+“->caller=“+ThisEnclosuringJoinPointStaticPart”);
//新异常(“打印堆栈跟踪”).printStackTrace(System.out);
//System.out.println();
返回继续(对象);
}
}
控制台日志:
call(void my.thirdparty.application.Foo.Foo())->caller=execution(void my.thirdparty.application.Foo.zot())
调用(void my.thirdparty.application.Foo.Foo())->caller=execution(void my.thirdparty.application.Bar.someMethod())
调用(void my.thirdparty.application.Foo.Foo())->caller=execution(void my.thirdparty.application.Foo.zot())
调用(void my.thirdparty.application.Foo.Foo())->caller=execution(void my.thirdparty.application.Foo.zot())
调用(void my.thirdparty.application.Foo.Foo())->caller=execution(void my.thirdparty.application.Bar())
调用(void my.thirdparty.application.Foo.Foo())->caller=execution(void my.thirdparty.application.Foo.zot())
调用(void my.thirdparty.application.Foo.Foo())->caller=execution(void my.thirdparty.application.Foo.zot())
调用(void my.thirdparty.application.Foo.Foo())->caller=execution(void my.thirdparty.application.Bar.anotherMethod())
调用(作废my.thirdparty.application.Foo.Foo(
package my.thirdparty.application;
public class Foo {
void blah() {
zot();
}
void foo() {}
void zot() {
foo();
}
}