0

在我的带有方面注释的 spring 控制器中,我试图删除 CGLib 代理并用 JDK 动态代理替换它们。我知道当类没有实现接口时 Spring AOP 使用 CGLib,因为 JDK 动态代理只在接口上工作。我还意识到,接口和实现类上都需要有注解。但是,我遇到的问题是控制器不再显示为带有 JDK 代理的 bean。

我的控制器 bean 像这样被扫描:

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

这可行,但控制器显示为 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

这不起作用,它永远不会到达 bean 后处理器:

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();
}

但是,如果我明确地创建这个 DynamicController bean,如

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

然后当我启动我的服务器时 ServletContext 抱怨说

bean初始化失败;嵌套异常是 java.lang.IllegalStateException:无法将处理程序“dynamicController”映射到 URL 路径 [some_url]:已经映射了类型为 [class $Proxy61] 的处理程序。

所以这里发生了一些事情,DynamicController 是一个动态代理。但我不知道还发生了什么,我知道它不再是一个 bean/控制器。我不想要“控制器、方面、动态代理:选择任何两个”我想要全部三个。这有可能吗?

4

2 回答 2

0

我不是 100% 确定您的 BeanPostProcessor 正在尝试做什么,或者您是否控制其中的代码,但假设它不是 Ordered 似乎是安全的,因此在创建代理后处理它(这将有默认最低优先级,但在无序之前)。也许你可以实现 Ordered 并给它一个低阶(比如 0)?

于 2012-12-11T15:36:07.687 回答
0

为了拿起这个 bean,我必须像以前那样在 postProcessBeforeInitialization 中处理它,而不是在 postProcessAfterInitialization 中处理它。我推测它在初始化时被代理了,这会搞砸一些事情。

正如我所暗示的,DynamicController 实际上是一个 JDK 动态代理,但代理背后的真正对象是 bean。然而!根据我丢失的某些来源,在使用代理和对接口进行编程时,注释必须在接口上。如果界面上没有它们,spring 不会知道。并且注释必须在具体类上才能使 bean 后处理器工作,仅在接口上是不够的。

于 2012-12-12T19:28:52.503 回答