为什么在 Spring AOP 中对象被包装到实现接口的 JDK 代理中? [英] Why in Spring AOP the object are wrapped into a JDK proxy that implements interfaces?

查看:27
本文介绍了为什么在 Spring AOP 中对象被包装到实现接口的 JDK 代理中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习 Spring 并且我有以下内容

I am studying Spring and I have the followig

考虑以下 bean 定义:

Consider the following bean definition:

<bean id="clientService" class="com.myapp.service.ClientServiceImpl" />

现在考虑将其声明为针对 **clientService bean 中所有方法的切入点* 的情况.

Now consider the case on which it is declared a pointcut* targetting all methods inside the **clientService bean.

还要考虑 ClientServiceImpl实现 3 个接口

现在我知道使用 AOP 代理 clientService bean 并且这个代理实现了所有 3 个接口.

Now I know that using AOP the clientService bean is proxied and that this proxy implements all the 3 interfaces.

但是实现这三个接口的确切原因是什么?

But what is the exact reason for which all these 3 interface are implemented?

所以在我看来存在两种代理(如果我说错误的断言,请纠正我):

So it seems to me that exist 2 kinds of proxies (correct me if I am saying wrong assertions):

  1. JDK 代理:在 Spring 中默认使用(这是真的吗?),因为我有一个接口来定义我想要代理的对象的方法.所以这个接口的具体实现是由代理包裹的.所以当我在我的对象上调用一个方法时,我是在它的代理上调用它.调用由方法拦截器识别,最终执行方面,然后执行调用的方法.

  1. JDK Proxy: used by default from Spring (is it true?) in wicht I have an interface that define the method of the object that I want to proxify. So the concrete implementation of this interface is wrapped by the proxy. So when I call a method on my object I am calling it on its proxy. The call is recognized by a method interceptor that eventually perform the aspect and then is performed the invoked method.

CGLIB 代理: 在我看来,代理扩展了包装对象的实现,为其添加了额外的逻辑功能

CGLIB Proxy: in wich, it seems to me that, the proxy extend the implementation of the wrapped object adding to it the extra logic features

像这样:

所以在我看来,Spring 使用了第一种基于接口实现的代理(对吗?):

So it seems to me that Spring use the first kind of proxy that is based on the implementation of interfaces (is it right?):

我认为在AOP中,额外的逻辑由方法拦截器的实现表示(是真的吗?)定义到接口中的方法.

I think that in AOP the extra logic is represented by the implementation of the method interceptor (is it true?) and the standard logic is represented by the implementation of the method defined into the interfaces.

但是,如果前面的推理是正确的,我的疑惑是:为什么我需要定义这些接口,并且对象包装的对象实现这些接口?(我无法理解代理本身是否实现了这些接口).

But, if the previous reasoning are correct, my doubts is: why I need to define these interface and do that the object wrapped by the object implement these interfaces? (I can't understand if the proxy itself implement these interfaces).

为什么?具体如何运作?

Why? How exactly works?

Tnx

推荐答案

但是所有这三个接口的确切原因是什么实施了吗?

But what is the exact reason for which all these 3 interface are implemented?

如果代理没有实现所有这些接口,则无法将该 bean 连接到使用该接口的其他 bean(您将得到 ClassCastException).例如,将该接口的所有 bean 自动装配到一个 bean 中.此外,诸如 getBeanNamesForType 将不起作用.

If the proxy didn't implement all of those interfaces, the bean couldn't be wired into other beans that use that interface (you'd get a ClassCastException). For example, autowiring all of the beans of that interface into a bean. Additionally, things like getBeanNamesForType wouldn't work if the proxy didn't implement the interface.

所以在我看来存在两种代理(如果我是,请纠正我说错误的断言)

So it seems to me that exist 2 kinds of proxies (correct me if I am saying wrong assertions)

是的,没错.请参阅ScopedProxyMode.默认情况下,Spring 不会创建代理.它仅在需要包装 bean 以添加附加行为 (AOP) 时才创建代理.请注意,还有 基于 CGLIB 的代理的一个特例,它使用 Objenesis 来处理没有默认构造函数的子类化目标.

Yes that's correct. See ScopedProxyMode. By default, Spring won't create a proxy. It only creates a proxy if it needs to wrap the bean to add additional behavior (AOP). Note that there's also a special case of the CGLIB based proxy that uses Objenesis to deal with subclassing targets that don't have a default constructor.

CGLIB 代理:在我看来,代理扩展了包装对象的实现添加了额外的逻辑特点

CGLIB Proxy: in wich, it seems to me that, the proxy extend the implementation of the wrapped object adding to it the extra logic features

当您使用基于 CGLIB 的代理时,bean 的构造函数会被调用两次:一次是在动态生成的子类被实例化时(以创建代理),第二次是在创建实际 bean 时(目标).

When you use CGLIB based proxies, the constructor for your bean gets called twice: once when the dynamically generated subclass is instantiated (to create the proxy) and a second time when the actual bean is created (the target).

我认为在 AOP 中,额外的逻辑由方法拦截器的实现(是真的吗?)

I think that in AOP the extra logic is represented by the implementation of the method interceptor (is it true?)

代理本质上只是调用需要应用的建议链.该建议并未在代理本身中实现.例如,@Transactional 的建议位于 TransactionAspectSupport.看一下源码JdkDynamicAopProxy.

The proxy is essentially just invoking the chain of advice needs to be applied. That advice isn't implemented in the proxy itself. For example, the advice for @Transactional lives in TransactionAspectSupport. Take a look at the source to JdkDynamicAopProxy.

标准逻辑由实现方法定义到接口中.

and the standard logic is represented by the implementation of the method defined into the interfaces.

假设您针对接口进行编程并使用正确的 JDK 代理.

Assuming that you're programming against interfaces and using JDK proxies that's correct.

但是,如果前面的推理是正确的,我的疑问是:为什么我需要定义这些接口并执行由对象包装的对象实现这些接口?(我不明白代理本身是否实现这些接口).

But, if the previous reasoning are correct, my doubts is: why I need to define these interface and do that the object wrapped by the object implement these interfaces? (I can't understand if the proxy itself implement these interfaces).

如果你想使用基于接口的代理,你需要使用接口.只要确保所有 bean 都实现接口,所有建议的方法都由这些接口定义,并且当一个 bean 依赖另一个 bean 时,使用接口指定该依赖项.Spring 将负责构建代理并确保它实现所有接口.

If you want to use interface based proxies you need to use interfaces. Just make sure all of your beans implement interfaces, all of your advised methods are defined by those interfaces, and that when one bean depends on another bean, that dependency is specified using an interface. Spring will take care of constructing the proxy and making sure it implements all of the interfaces.

在您的图表中,您有Spring AOP Proxy (this)".当您使用任何类型的代理时,您必须非常小心地使用 this.

In your diagram, you have "Spring AOP Proxy (this)". You have to be really careful with using this when you're using any type of proxying.

  1. 同一类中的调用不会应用通知,因为这些调用不会通过代理.
  2. 如果在您的一个 bean 中将 this 传递给某些外部代码,则您正在传递 AOP 建议的目标.如果其他代码使用该引用,则调用将不会应用 AOP 建议(同样,您绕过了代理).
  1. Calls within the same class won't have advice applied because those calls won't pass through the proxy.
  2. If in one of your beans you pass this to some outside code, you're passing the target of the AOP advice. If some other code uses that reference, the calls won't have AOP advice applied (again, you're bypassing the proxy).

这篇关于为什么在 Spring AOP 中对象被包装到实现接口的 JDK 代理中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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