INTERFACES或TARGET_CLASS:我应该选择哪个proxyMode?

You*_*sef 31 spring spring-mvc

我正在寻找一种存储我的对象的方法,似乎最好的方法是使用代理.我在互联网上找到了2个注释,我应该使用哪个注释:

@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
Run Code Online (Sandbox Code Playgroud)

要么

@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS )
Run Code Online (Sandbox Code Playgroud)

此外,代理是否是使用@Component @Scope("session")或使用的最佳方式@SessionAttributes

Sot*_*lis 27

这不是关于哪个更好.它们每个都有自己的功能集.使用接口进行代理意味着Spring将使用只能获取目标bean的接口类型的JDK代理.使用目标类进行代理意味着Spring将使用CGLIB代理,这些代理可以获取目标bean的类和接口类型.适当时使用它们.

请参阅javadoc.

使用Foo不是会话范围bean的替代方法.会话属性只是对象,它们不是bean.它们不具备bean可能具有的完整生命周期,注入功能和代理行为.


Ang*_*ity 26

如果要将整个bean存储在会话中,请使用@Scope,否则使用@SessionAttributes.在使用@Scope的情况下,如果类实现了某些接口,则使用INTERFACES代理模式,如果不使用TARGET_CLASS.

通常,您的服务实现了一个接口,允许使用JDK代理(INTERFACES模式).但如果不是这种情况,那么使用TARGET_CLASS,它创建一个CGLIB代理.

如果可能的话,应该使用INTERFACES,如果bean没有实现接口,则使用TARGET作为最后的手段.


小智 6

在浏览上面评论中提供的博客文章时,我发现了一条评论说明了基于接口的代理的缺点.

在帖子上,用户FlemmingJønsson发布了这样的信息:

小心使用基于接口的代理.

如果您使用的是Spring Security或Spring Transactions,则在使用基于接口的代理时可能会遇到奇怪的问题.

例如,如果你有一个bean T,那个bean的方法a()和b()都是带注释的事务.从其他bean直接调用a()或b()将正常运行(如配置).但是,如果引入内部调用 - 其中a()调用b(),则b的事务元数据将不起作用.原因是当您使用基于接口的代理时,内部调用将不会通过代理 - 因此事务拦截器将无法启动新事务.

安全性也是如此.如果方法a()只需要USER-role但是调用需要ADMIN-role的b(),那么将对任何没有警告的USER执行从a到b的内部调用.与上述相同的原因是,内部调用不通过代理,因此安全拦截器没有机会对来自()的b()调用进行操作.

要解决这些问题,请使用targetClass.

  • 这不是特定于基于接口的代理,CGLIB代理也有相同的问题. (8认同)