您需要了解每个注释的作用,以便自行选择。请参阅javadoc,
这里。继续阅读以获取更详细的解释。
第一个
@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
创建
使用JDK动态代理实现目标对象类所暴露的所有接口。
换句话说,代理将是目标对象类实现的接口的子类型,但不会是目标对象类本身的子类。
基本上,Spring执行以下操作
public class Example {
public static void main(String[] args) throws Exception {
Foo target = new Foo();
InvocationHandler proxyHandler = ...
Printable proxy = (Printable) Proxy.newProxyInstance(Example.class.getClassLoader(),
target.getClass().getInterfaces(), proxyHandler);
Foo foo = (Foo) proxy;
}
public static class Foo implements Printable {
@Override
public void print() {
}
}
public interface Printable {
void print();
}
}
代理返回的类型不会是
Foo
,因此您无法将其注入到该类型的任何目标中。例如,Spring将无法将其注入到类似于以下字段的字段中。
@Autowired
private Foo foo;
但是它将成功地将代理注入到类似字段中。
@Autowired
private Printable printable
所有对代理的调用都将由
InvocationHandler
处理(通常执行一些特定于用例的逻辑,然后委托给目标对象)。
第二个注释
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS )
创建
基于类的代理(使用CGLIB)。
除了接口外,使用CGLIB,Spring还能够创建一个类是目标类子类的代理。本质上,它执行以下操作:
Foo target = new Foo();
net.sf.cglib.proxy.Enhancer enhancer = new net.sf.cglib.proxy.Enhancer();
enhancer.setInterfaces(target.getClass().getInterfaces());
enhancer.setSuperclass(target.getClass());
net.sf.cglib.proxy.MethodInterceptor interceptor = ...
enhancer.setCallback(interceptor);
Foo proxy = (Foo) enhancer.create();
CGLIB会创建一个
Foo
子类的新类并实例化它(调用
Foo
的构造函数)。所有对代理的调用都将被提供的回调拦截(通常执行一些用例特定逻辑,然后委托给目标对象)。
由于代理类扩展了
Foo
,因此Spring可以将代理注入到字段(或构造函数/方法参数)中。
@Autowired
private Foo injectMe
所有这些都是为了说,如果你正在
编程到接口,那么
ScopedProxyMode.INTERFACES
就足够了。如果不是,则使用
ScopedProxyMode.TARGET_CLASS
。
关于使用
@SessionAttributes,它并不是会话作用域bean的替代品。会话属性只是对象,它们不是bean。它们没有完整的生命周期、注入能力和代理行为,这些是bean可能具有的。