Search code examples
springproxycontrollerspring-aopcglib

How to get Spring Controllers, AOP and JDK Proxy to work together


In my spring controllers, annotated with aspects, I am attempting to remove CGLib proxies and replace them with JDK dynamic proxies. I know that Spring AOP uses CGLib when the class does not implement an interface, since JDK dynamic proxies work only on interfaces. I also realize that annotations need to be present on both the interface and the implementing class. However, the problem I am running into is that the controller no longer shows up as a bean with a JDK proxy.

My controller bean is scanned for like such:

<context:annotation-config/>
<context:component-scan base-package="com.package.name"/>

This works, but controller shows up as CGLibController$$EnhancerByCGLIB$$5f0b2287:

package com.package.name;
@Controller
public class CGLibController {
  @AOP_Aspect
  @RequestMapping("some_url")
  public void foo();
}

//in a bean post processor
//in postProcessAfterInitialization(Object bean, String beanName)
  Controller controller = AnnotationUtils
      .findAnnotation(bean.getClass(), Controller.class);
//controller will exist
//bean name is CGLibController$$EnhancerByCGLIB$$5f0b2287

This doesn't work, it never gets to the bean post processor:

package com.package.name;
@Controller
public interface ITest{
  @AOP_Aspect
  @RequestMapping("some_url")
  public void foo();
}

package com.package.name;
@Controller
public class DynamicController implements ITest{
  @AOP_Aspect
  @RequestMapping("some_url")
  public void foo();
}

However, if I explicitly create this DynamicController bean as in

<bean class="com.package.name.DynamicController"/>

then when I start up my server the ServletContext complains that

Initialization of bean failed; nested exception is java.lang.IllegalStateException: Cannot map handler 'dynamicController' to URL path [some_url]: There is already handler of type [class $Proxy61] mapped.

So something is happening here, DynamicController is a dynamic proxy. But I don't know what else is happening and I know it's not a bean/controller any longer. I don't want "controller, aspect, dynamic proxy: pick any two" I want all three. Is this possible somehow?


Solution

  • In order to pick up this bean I had to handle it in postProcessBeforeInitialization NOT postProcessAfterInitialization like I was doing before. I surmise that it is proxied when initialized and that messes up something.

    As I hinted at, DynamicController is in fact a JDK dynamic proxy, but the real object behind the proxy is the bean. However! when using proxies and programming to interfaces, the annotations must be on the interface, according to some source which I have lost. Without them on the interface, spring wouldn't know. AND the annotations must be on the concrete class in order for the bean post processor to work, on the interface alone is not enough.