我有一个像这样的接口驱动控制器:
@ResponseBody
@PreAuthorize("hasAnyRole('ADMIN', 'USER')")
@RequestMapping("/foo")
interface Foo {
@GetMapping("/{id}")
String bar(String id);
}
和委托给实际业务逻辑的实现
@Controller
public class FooImpl implements Foo {
@Override
public String bar(String id) {
return "<actual business logic>";
}
}
我想装饰接口Foo
添加到应用程序的附加功能。
然而,当我使用jdk代理并尝试使用该spring启动应用程序时,它将不再注册端点。这是因为bean类型上不再使用@Controller
进行注解。注解只存在于实现中(我不能使用@Bean
方法,因为该注解只允许在类型上使用),而不是代理,现在spring web mvc看到的类型。我也不能用@Controller注解装饰和实现,因为那样我将有不明确的Map,因为装饰接口和实现将被视为需要为其创建处理程序Map的组件。
我还希望在实际业务逻辑的实现中保留控制器注解,以便控制器的主要焦点仍然很明显。
那么,我如何在spring web mvc中装饰一个接口驱动的控制器,同时保持实际的实现和任何应该应用到它的装饰是不同的呢?
2条答案
按热度按时间ee7vknir1#
我创建了一个额外的接口,用于将
@Controller
注解添加回已创建的代理:我将这个接口附加地传递给用于创建代理示例的
java.lang.reflect.Proxy.newProxyInstance(ClassLoader, Class<?>[], InvocationHandler)
调用的接口。这样spring仍然会将装饰的示例视为控制器。然而,如果将有更多注解以这种方式应用,则这将不会缩放。
tyu7yeag2#
在Spring Controller中使用代理需要基于类的代理,参考指南中甚至有一节解释了这一点,并对Spring Framework 6中的更改进行了额外的说明。
要在所有注解中强制启用类代理,您必须使用代理,如
@EnableTransactionManagement
,@EnableAspectJAutoProxy
等。