在同一方法上使用@Secured和@RequestMapping时的ClassFormatError

时间:2012-03-16 16:37:47

标签: java spring-mvc spring-security

当我尝试在已使用@Secured注释的@PreAuthorize方法中使用@Controller@RequestMapping时,我发现了一个奇怪的错误。当我尝试启动应用程序时,它给出了以下错误(使用带有vFabric 2.6.1的spring STS 2.8.1在win 7 32位上,包括springframework和spring security 3.1):

Caused by: java.lang.ClassFormatError: Duplicate method name&signature in class file com/dnp/web/controllers/HomeController
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
    at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:2820)
    at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1150)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1645)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1523)
    at org.springframework.util.ClassUtils.forName(ClassUtils.java:258)
    at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:417)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(AbstractBeanFactory.java:1283)
    at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1254)
    ... 43 more

控制器代码:

@Controller
public class HomeController {

    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

    @PreAuthorize("hasRole('ROLE_USER')")
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(Locale locale, Model model) {
        logger.info("Welcome home! the client locale is "+ locale.toString());

        Date date = new Date();
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);

        String formattedDate = dateFormat.format(date);

        model.addAttribute("serverTime", formattedDate );

        return "home";
    }
}

我不知道为什么会抛出这个错误,并且没有在互联网上找到任何关于它的信息。此外,服务层上的安全注释也可以正常工作。

PD:完整的应用程序跟踪在这里:http://pastebin.com/raw.php?i=VxdYPDXL,安全和servlet上下文的主要部分在这里:http://pastebin.com/cva5VgkH

3 个答案:

答案 0 :(得分:0)

@rabusmar,我从SpringForum获得了这个链接 http://forum.springsource.org/showthread.php?109850-RequestMapping-and-PreAuthorize-not-compatible

似乎PreAuthorize和Request Mapping不兼容。他们在页面末尾给出了解决方案。试试吧。

此外,当一个已经由一个注释检测的类被另一个注释再次检测时,就会出现ClassFormatError,在这种情况下,HomeController可能已经由PreAuthorize和RequestMapping再次检测,反之亦然,这就是你得到的原因。 ClassFormatError。

您可以在我上面提供的春季论坛链接中尝试解决方案。

答案 1 :(得分:0)

似乎这个问题是由Spring AOP和AspectJ编译时编织相同方法之间的一些奇怪冲突造成的:我正在使用一个方面来建议控制器方法调用,它是编译时编织的控制器。因此,解决方案只是禁用AspectJ编译,现在它可以正常工作。

答案 2 :(得分:0)

我在一些groovy代码中遇到了类似的ClassFormatError。但错误消息没有说明哪个方法名称和签名是重复的。

我通过运行以下命令找到了错误:

javap -private -c io.cloudsoft.mapr.m3.MasterNodeImpl | grep -A 1 '^$' | sort | uniq -c | less

这找到了所有方法签名(在我的javap输出中始终以空行开头),然后计算唯一出现次数,以便我可以看到哪个方法签名是重复的。我希望别人这么好用。

(对于那些感兴趣的人,我的问题是groovy的@InheritConstructors的奇怪行为,它以某种方式添加了两次no-arg构造函数。)