接口或TARGET_CLASS:我应该选择哪个proxyMode? [英] INTERFACES or TARGET_CLASS: Which proxyMode should I choose?

查看:152
本文介绍了接口或TARGET_CLASS:我应该选择哪个proxyMode?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种存储对象的方法,看来最好的方法是使用代理.我在互联网上发现了2个注释,我应该使用其中一个:

I am looking for a way to store my object and it seems that the best approach is to use proxies. I found 2 annotation in the internet, which one should I use :

@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)

@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS )

而且,与使用@Component @Scope("session")@SessionAttributes相比,代理服务器是最佳的使用方式吗?

Moreover, is it true that the proxies is the best way to use than using @Component @Scope("session") or using @SessionAttributes?

推荐答案

您需要了解这些注释各自为自己选择的功能.请参见Javadoc,此处.继续进行更详细的说明.

You'll need to understand what each of those annotations does to choose for yourself. See the javadoc, here. Continue for a more detailed explanation.

第一个

@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)

创建

一个JDK动态代理,实现了目标对象的类公开的 all 接口

换句话说,代理将是目标对象的类实现的接口的子类型,但不会是目标对象的类本身的子类.

In other words, the proxy will be a subtype of the interfaces that the target object's class implements, but won't be a subclass of the target object's class itself.

基本上Spring会执行以下操作

Essentially Spring does the following

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将无法将其注入到类似

The proxy returned won't be of type Foo and you therefore can't inject it into any targets of that type. For example, Spring will fail to inject it into a field like

@Autowired
private Foo foo;

但将成功将代理注入到类似

but will successfully inject the proxy into a field like

@Autowired
private Printable printable;

所有对代理的调用将由InvocationHandler处理(通常执行一些用例特定的逻辑,然后委派给目标对象).

All calls to the proxy will be handled by the InvocationHandler (which usually performs some use case specific logic then delegates to the target object).

第二个注释

@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS )

创建

基于类的代理(使用CGLIB).

a class-based proxy (uses CGLIB).

除了接口之外,Spring还可以使用CGLIB创建一个代理,该代理的类是目标类的子类.本质上,它执行以下操作

In addition to interfaces, with CGLIB Spring will be able to create a proxy whose class is a subclass of the target's class. In essence, it does the following

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 fine
Foo proxy = (Foo) enhancer.create();

CGLIB创建一个新类,该类是Foo的子类,并将其实例化(调用Foo的构造函数).所有对代理的调用都会被提供的回调拦截(通常会执行一些用例特定的逻辑,然后委托给目标对象).

CGLIB creates a new class that is a subclass of Foo and instantiates it (invoking the constructor of Foo). All calls to the proxy will be intercepted by the provided callback (which usually performs some use case specific logic and then delegates to the target object).

由于代理类扩展了Foo,因此Spring可以将代理注入到类似

Since the proxy class extends Foo, Spring can inject the proxy into a field (or constructor/method parameter) like

@Autowired
private Foo injectMe;


这一切都是说,如果您编程为接口,那么ScopedProxyMode.INTERFACES就足够了.如果不是,请使用ScopedProxyMode.TARGET_CLASS.


All this to say, if you're programming to interfaces, then ScopedProxyMode.INTERFACES will be sufficient. If you're not, then use ScopedProxyMode.TARGET_CLASS.

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

As for using @SessionAttributes, it is not an alternative to session scoped beans. Session attributes are just objects, they are not beans. They don't possess the full lifecycle, injection capabilities, proxying behavior that a bean may have.

这篇关于接口或TARGET_CLASS:我应该选择哪个proxyMode?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆