Ban*_*ane 6 logging aop spring
我编写了一个简单的Spring2.5应用来演示/测试AOP; 具体来说,我想记录特定包中每个类的每个方法的进入和退出.这就是我所拥有的......
(注意:我正在使用注释控制器;我省略了与aop没有直接关系的细节,因为我的基本设置工作正常 - 我只包含与aop相关的详细信息 - 如果你需要了解更多,请告诉我)
applicationContext.xml:
(...)
<bean id="loggerInterceptor" class="aspect.LoggerInterceptor" />
(...)
Run Code Online (Sandbox Code Playgroud)
dispatcher-servlet.xml:
(...)
<aop:aspectj-autoproxy proxy-target-class="true" />
(...)
Run Code Online (Sandbox Code Playgroud)
HomeController.java:
public class HomeController() {
public HomeController() { }
public ModelAndView get() {
System.out.println("In HomeController#get()...");
this.somePrivateMethod();
this.somePublicMethod();
return new ModelAndView( "home" );
}
private void somePrivateMethod() {
System.out.println("In HomeController#somePrivateMethod()...");
}
public void somePublicMethod() {
System.out.println("In HomeController#somePublicMethod()...");
}
}
Run Code Online (Sandbox Code Playgroud)
LoggerInterceptor.java:
public class LoggerInterceptor {
@Pointcut("execution(* controller.*.*(..))")
private void anyOperationInControllerPackage() {
/* nothing to do here;
* this just defines that we want to catch all methods
* in the controller-package
*/
}
@Around("anyOperationInControllerPackage()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("Entering " + joinPoint.getSignature().getDeclaringTypeName() + "#" + joinPoint.getSignature().getName() + "() using arguments: " + Arrays.toString( joinPoint.getArgs() ) );
try {
Object result = joinPoint.proceed();
System.out.println("Leaving " + joinPoint.getSignature().getDeclaringTypeName() + "#" + joinPoint.getSignature().getName() + "()." );
return result;
} catch (Throwable ex) {
ex.printStackTrace();
throw ex;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我在调用HomeController#get()时得到的:
Entering controller.HomeController#get() using arguments: []
In HomeController#get()...
In HomeController#somePrivateMethod()...
In HomeController#somePublicMethod()...
Leaving controller.HomeController#get().
Run Code Online (Sandbox Code Playgroud)
如您所见,被拦截的唯一方法是HomeController#get().当#get()调用#somePrivateMethod()或#somePublicMethod()时,拦截器不会捕获它们.我希望,至少#somePublicMethod()也会被捕获(因为我正在使用cglib,我也希望#somePrivateMethod()会被捕获).
所以我想我的问题是我需要更改/添加什么才能允许(至少)控制器包中的所有公共方法被捕获,即使该包中的另一个方法调用它们并且本身首先被捕获? ??
我希望这是有道理的.:d
applicationContext.xml:
(...)
<context:load-time-weaver /> <!-- added -->
<bean id="loggerInterceptor"... />
(...)
Run Code Online (Sandbox Code Playgroud)
aop.xml:
<!DOCTYPE aspectj PUBLIC
"-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver>
<!-- only weave classes in this package -->
<include within="controller.*" />
</weaver>
<aspects>
<!-- use only this aspect for weaving -->
<aspect name="aspect.LoggerInterceptor" />
</aspects>
</aspectj>
Run Code Online (Sandbox Code Playgroud)
在Netbean的"运行"选项卡下的"项目属性"中,我将此行添加到"VM选项":
-javaagent:C:\Users\bgresham\Documents\libraries\spring-framework-2.5\dist\weaving\spring-agent.jar
Run Code Online (Sandbox Code Playgroud)
和以前一样,我没有收到任何错误 - 我只是没有得到"嵌套" - 我正在寻找的记录.
???
您正在使用 spring aop 来支持方面。Spring aop 仅适用于 spring beans。因此,切入点不适用于实际的类实例,即当控制器调用其任何公共或私有方法时。为了记录控制器中的所有方法,您需要通过启用您想要拦截的所有类的加载时或编译时编织来使用 AspectJ 来支持 aop。编辑:
您需要以下内容来进行加载时编织:
aop.xml
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver options="-Xset:weaveJavaxPackages=true -verbose -showWeaveInfo -debug">
<include within="*"/>
</weaver>
<aspects>
<!-- weave in just this aspect -->
<aspect name="your.logger.impl.LoggingImpl"/>
</aspects>
</aspectj>
Run Code Online (Sandbox Code Playgroud)
这意味着使用指定的方面编织所有文件('within=*',根据需要修改)。在加载时,您应该看到有关类编织的详细信息。
弹簧配置中的配置:
<context:load-time-weaver aspectj-weaving="autodetect"
weaver-class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>
Run Code Online (Sandbox Code Playgroud)
请注意,编织类必须位于服务器库路径中,而不是您的应用程序路径中。
上述配置应该可以满足您的要求。
如果你正在使用Spring AOP,你必须只通过Spring返回的引用调用一个已经应用了方面的方法,而不是通过this,并且我不认为你可以将切入点应用于私有方法(可能是错误的最后一部分).那是因为Spring AOP通过代理对象应用切入点,而不是通过类重写(这是AspectJ所做的).这个重要限制的好处是,它更容易使它在容器中工作(我从经验中知道Spring AOP在Tomcat中运行得很好),因为没有争论插入的位置在哪里.
这样做的最好方法是拆分类定义,以便永远不会调用方法this,但如果不可能,那么你总是可以尝试给bean一个Spring派生的引用:
private HomeController self;
@Required
public void setSelf(HomeController self) { this.self = self; }
public ModelAndView get() {
System.out.println("In HomeController#get()...");
self.somePrivateMethod();
self.somePublicMethod();
return new ModelAndView( "home" );
}
Run Code Online (Sandbox Code Playgroud)
(这非常简洁; self是许多语言中的关键字,但不是Java,所以记住你正在使用它的相对容易.)
| 归档时间: |
|
| 查看次数: |
8102 次 |
| 最近记录: |