当Struts2的Action继承ActionSupport时,利用AOP来拦截Action出现NoSuchMethodException when Aspec...

今天做项目的时候,由于要用到在Struts2的Action类中利用Spring的AOP来实现记录操作日志,在Action里面的方法中加上自定义annotation来实现记录操作功能,运行的时候页面提示NoSuchMethodException when Aspec,网上说是Action继承了ActionSupport导致的,后来在一个英文网站上找到了解决的方法,只要在Spring的配置文件applicationContext中的<aop:aspectj-autoproxy/>改为<aop:aspectj-autoproxy proxy-target-class="true"/>就可以了。

英文网站的地址是:http://forum.springsource.org/showthread.php?t=51758,原文如下:

 

Default NoSuchMethodException when Aspecting classes

<!-- / icon and title --><!-- message -->

Hi everyone,

I'm new to Aspects and I'm having trouble configuring them inside Spring, I have some questions to ask:

First, configuration issues, I've got defined these beans provided by Appfuse (2.0):
Code:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"
       default-lazy-init="true">

    <!-- =================================================================== -->
    <!-- AOP: Configuration and Aspects                                      -->
    <!-- =================================================================== -->
    <aop:config>
        <aop:advisor id="userManagerTx" advice-ref="userManagerTxAdvice" pointcut="execution(* *..service.UserManager.*(..))" order="0"/>        
        <aop:advisor id="userManagerSecurity" advice-ref="userSecurityAdvice" pointcut="execution(* *..service.UserManager.saveUser(..))" order="1"/>
        <aop:advisor id="managerTx" advice-ref="txAdvice" pointcut="execution(* *..service.*Manager.*(..))" order="2"/>
    </aop:config>
    
    <!-- Enable @Transactional support -->
    <tx:annotation-driven/>
    
    <!-- Fix bug in Spring 2.0.6: http://issues.appfuse.org/browse/APF-887 -->
    <bean class="org.springframework.transaction.aspectj.AnnotationTransactionAspect" factory-method="aspectOf" dependency-check="none" lazy-init="false">
        <property name="transactionManager" ref="transactionManager"/>
    </bean>
    
    <!-- Enable @AspectJ support -->
    <aop:aspectj-autoproxy/>

    <!-- Enable @Configured support -->
    <aop:spring-configured/>
    
    <tx:advice id="txAdvice">
        <tx:attributes>
            <!-- Read-only commented out to make things easier for end-users -->
            <!-- http://issues.appfuse.org/browse/APF-556 -->
            <!--tx:method name="get*" read-only="true"/-->
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

    <tx:advice id="userManagerTxAdvice">
        <tx:attributes>
            <tx:method name="save*" rollback-for="UserExistsException"/>
        </tx:attributes>
    </tx:advice>
    
    <bean id="userSecurityAdvice" class="org.appfuse.service.UserSecurityAdvice"/>
    
    [...]
These beans are defined inside an applicationContext file inside one of appfuse jars, so I cannot change them (although I do overwrite some other appfuse bean). I do need to keep the aop:config section, as it being used by our application.

And I've also defined (in our own applicationContext file) a couple of beans to implement logging when some subpackaging is detected or when detecting some annotations:

Code:
  <bean id="aLogInterceptor" class="com.bungee.aspects.AnnotationLoggerInterceptor" />
  <bean id="cpLogInterceptor" class="com.bungee.aspects.PackagesLoggerInterceptor" />
Next the @AspectJ class:

Code:
@Aspect
public class PackagesLoggerInterceptor {

    @Before( "execution( * com.bungee..*.*(..) ) && !execution( * com.bungee.aspects.*.*(..) )" )
    public void beforeMethod( JoinPoint jp ) {
	// logging in here
    }
    
    @AfterReturning( pointcut = "execution( * com.bungee..*.*(..) ) && !execution( * com.bungee.aspects.*.*(..) )", returning="retVal" )
    public void afterMethod( JoinPoint jp, Object retVal ) {
	// more logging in here...
    }
    
    @AfterThrowing( pointcut = "execution( * com.bungee..*.*(..) ) && !execution( * com.bungee.aspects.*.*(..) )", throwing="ex" )
    public void afterException( JoinPoint jp, Throwable ex ) {
	// ... and finish logging here
    }
    
}
Ok, first problem in here, I've got some Struts2 actions under package com.bungee.webapp.action. Each time one of those classes gets invoked I've got the same type of Exception:


Code:
java.lang.NoSuchMethodException: $Proxy361.initHome()
	at java.lang.Class.getMethod(Class.java:1605)
	at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.getActionMethod(AnnotationValidationInterceptor.java:55)
	at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:41)
	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:86)
	at com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
	at com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
	at com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
	at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:123)
	at com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
	at com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:223)
	at com.opensymphony.xwork2.util.profiling.UtilTimerStack.profile(UtilTimerStack.java:455)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:221)
	at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:167)
	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:86)
	at com.opensymphony.xwork2.DefaultActionInvocation$2.doProfiling(DefaultActionInvocation.java:224)
[...]
I've readed about aspects aren't getting well proxied, but I haven't been able neither to configure them properly nor finding how to do it. Any help would be greatly appreciated O:-)

Second issue, is @AfterThrowing well defined (I want to catch all type of Exceptions)?? I'm not very sure

And last issue, this time regarding AnnotationLoggerInterceptor: that class has more or less the same methods as PackagesLoggerInterceptor but changing the annotations to check for annotated methods or classes, so pointcuts are defined as follows:
Code:
@annotation( com.bungee.annotations.Loggeable )
Does this captures annotated classes and methods or only annotated methods?? I find Spring documentation a little unclear at this point.

I'm using AspectJ 1.5.3, Spring 2.0.6, Apffuse2.0 (Struts2 + ibatis flavour) and Java6

Thanks in advance!



found what was going wrong by myself: As noted several -lots of- times on this forum, I had to use proxy-target-class attribute, in order to use our Aspect (also) with Struts2 action classes, as jdk-proxies only work with interfaces.

Code:
<aop:aspectj-autoproxy proxy-target-class="true"/>
The problem was, this bean was declared in an applicationContext file inside an appfuse jar, without this attribute. I was trying to overwrite this bean on our own applicationContext file (which is setted to load afterwards), but it seems that Springs does not overwrite it, hence the error. We've moved all beans declared inside the appfuse jar to our applicationContext file, redeclared autoproxy as noted above, and removed this appfuse's applicationContext file from our list of applicationContext files.

Regards,
Michael K.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值