spring-projects / spring-framework

Spring Framework
https://spring.io/projects/spring-framework
Apache License 2.0
56.63k stars 38.14k forks source link

HandlerMethod.getBeanType() doesn't fully handle CGLIB-generated classes [SPR-9490] #14124

Closed spring-projects-issues closed 12 years ago

spring-projects-issues commented 12 years ago

Thomas Bruyelle opened SPR-9490 and commented

https://github.com/SpringSource/spring-framework/blob/master/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java#L122

   /**
 * Returns the type of the handler for this handler method.
 * Note that if the bean type is a CGLIB-generated class, the original, user-defined class is returned.
 */
public Class<?> getBeanType() {
     if (bean instanceof String) {
          String beanName = (String) bean;
          return beanFactory.getType(beanName);
     }
     else {
          return ClassUtils.getUserClass(bean.getClass());
     }
}

When bean instanceof String is true, the method returns the CGLIB-generated class instead of the user-defined one.

ClassUtils.getUserClass() should also wrap the return of beanFactory.getType( beanName ).


Affects: 3.1.1, 3.2 M1

spring-projects-issues commented 12 years ago

Rossen Stoyanchev commented

Out of curiosity how did you run into this use case? Typically the AbstractHandlerMethodMapping resolvers the bean name into a bean (around line 234, in the getHandlerInternal method) before it gets to the HandlerAdapter.

spring-projects-issues commented 12 years ago

Thomas Bruyelle commented

I'm currently trying to generate api docs on my project with a Spring MVC module of Swagger. Swagger is an api docs generator for restfull webapp.

The error occurs in the MvcApiReader class of this module.

What the module does :

handlerMappingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.context, HandlerMapping.class, true, false);

I'm not an expert of BeanFactory manipulation so I'm not sure all the steps above are correct.

About bean name resolving into a bean, I'm not sure to understand what do you mean. I really think the problem is in the getBeanType() method. The javadoc explicitly says the method doesn't return CGLIB-generated class, but actually it does.

spring-projects-issues commented 12 years ago

Rossen Stoyanchev commented

Thanks for the detail.

About bean name resolving into a bean, I'm not sure to understand what do you mean. I really think the problem is in the getBeanType() method. The javadoc explicitly says the method doesn't return CGLIB-generated class, but actually it does.

I was merely referring to the fact that the bean property of HandlerMethod can either be a String-based bean name or an actual bean instance. This helps to avoid instantiating controllers unnecessarily when we look them up on startup in the ApplicationContext. You'll see that HandlerMethod.createWithResolvedBean() can turn the bean name into a bean instance.

That aside, yes there is a bug which is why I set the fix version to 3.2 M2.

spring-projects-issues commented 12 years ago

Thomas Bruyelle commented

Thank you I understand now why a bean can be a String in HadnlerMethod.