您需要了解这些注释各自为自己选择的功能。在此处查看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 = ... // some proxy specific logic, likely referencing the `target` // works fine Printable proxy = (Printable) Proxy.newProxyInstance(Example.class.getClassLoader(), target.getClass().getInterfaces(), proxyHandler); // not possible, ClassCastException Foo foo = (Foo) proxy; } public static class Foo implements Printable { @Override public void print() { } } public interface Printable { void print(); }}返回的代理将不是此类型
Foo,因此您不能将其注入该类型的任何目标中。例如,Spring将无法将其注入到类似
@Autowiredprivate Foo foo;
但会成功将代理注入到类似
@Autowiredprivate Printable printable;
所有对代理的调用都将由处理
InvocationHandler(通常会执行一些用例特定的逻辑,然后委托给目标对象)。
第二注
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS )
创造
基于类的代理(使用CGLIB)。
除了接口之外,Spring还可以使用CGLIB创建一个代理,该代理的类是目标类的子类。本质上,它执行以下操作
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 = ... // some proxy specific logic, likely referencing the `target`enhancer.setCallback(interceptor);// works fineFoo proxy = (Foo) enhancer.create();
CGLIB创建一个新类,
Foo并将其实例化(调用的构造函数
Foo)。提供的回调将拦截对代理的所有调用(该回调通常执行一些用例特定的逻辑,然后委托给目标对象)。
由于代理类已扩展
Foo,Spring可以将代理注入到字段(或构造函数/方法参数)中,例如
@Autowiredprivate Foo injectMe;
这么说,如果您正在对interfaces进行编程,那么
ScopedProxyMode.INTERFACES就足够了。如果不是,请使用
ScopedProxyMode.TARGET_CLASS。
至于使用
@SessionAttributes,它不是会话范围的Bean的替代方案。会话属性只是对象,它们不是bean。它们不具备bean可能具有的完整生命周期,注入功能和代理行为。



