为什么在 Spring AOP 中将对象包装到实现接口的 JDK 代理中?
Why in Spring AOP the object are wrapped into a JDK proxy that implements interfaces?
我正在学习Spring并且我有followig
考虑以下 bean 定义:
<bean id="clientService" class="com.myapp.service.ClientServiceImpl" />
现在考虑声明为 pointcut* 的情况,目标是 **clientService bean 中的所有方法。
还要考虑 ClientServiceImpl class 实现 3 个接口
现在我知道使用 AOP clientService bean 被代理并且这个代理实现了所有 3 个接口。
但是实现这三个接口的确切原因是什么?
所以在我看来存在两种代理(如果我说错了断言请纠正我):
JDK Proxy:默认使用 Spring(是真的吗?)我有一个定义的接口我要代理的对象的方法。所以这个接口的具体实现是被代理包裹起来的。所以当我在我的对象上调用一个方法时,我是在它的代理上调用它。该调用由 方法拦截器 识别,最终执行方面,然后执行调用的方法。
CGLIB 代理: 在我看来,代理扩展了包装对象的实现,向其添加了额外的逻辑功能
像这样:
所以在我看来Spring使用第一种基于接口实现的代理(对吗?):
我认为在 AOP 中,额外的逻辑由 方法拦截器 的实现(是真的吗?)和标准逻辑由接口中定义的方法的实现来表示。
但是,如果前面的推理是正确的,我的疑惑是:为什么我需要定义这些接口并让对象包装的对象实现这些接口? (我无法理解代理本身是否实现了这些接口)。
为什么?具体如何运作?
Tnx
But what is the exact reason for which all these 3 interface are
implemented?
如果代理没有实现所有这些接口,则无法将该 bean 连接到使用该接口的其他 bean(您会得到 ClassCastException)。例如,将该接口的所有 bean 自动装配到一个 bean 中。此外,如果代理没有实现接口,getBeanNamesForType 之类的东西将无法工作。
So it seems to me that exist 2 kinds of proxies (correct me if I am
saying wrong assertions)
是的,没错。请参阅 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,它使用 Objenesis 来处理没有默认构造函数的子classing 目标。
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 的构造函数被调用两次:一次是在实例化动态生成的子 class 时(以创建代理),第二次是在创建实际 bean 时(目标)。
I think that in AOP the extra logic is represented by the
implementation of the method interceptor (is it true?)
代理本质上只是调用需要应用的通知链。该建议并未在代理本身中实现。例如,@Transactional
的建议位于 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 代理。
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 将负责构建代理并确保它实现所有接口。
在你的图表中,你有 "Spring AOP Proxy (this)"。当您使用任何类型的代理时,您必须非常小心地使用 this
。
- 同一 class 内的调用不会应用建议,因为这些调用不会通过代理。
- 如果在您的一个 bean 中将
this
传递给一些外部代码,那么您传递的是 AOP 建议的目标。如果其他一些代码使用该引用,调用将不会应用 AOP 建议(同样,您正在绕过代理)。
我正在学习Spring并且我有followig
考虑以下 bean 定义:
<bean id="clientService" class="com.myapp.service.ClientServiceImpl" />
现在考虑声明为 pointcut* 的情况,目标是 **clientService bean 中的所有方法。
还要考虑 ClientServiceImpl class 实现 3 个接口
现在我知道使用 AOP clientService bean 被代理并且这个代理实现了所有 3 个接口。
但是实现这三个接口的确切原因是什么?
所以在我看来存在两种代理(如果我说错了断言请纠正我):
JDK Proxy:默认使用 Spring(是真的吗?)我有一个定义的接口我要代理的对象的方法。所以这个接口的具体实现是被代理包裹起来的。所以当我在我的对象上调用一个方法时,我是在它的代理上调用它。该调用由 方法拦截器 识别,最终执行方面,然后执行调用的方法。
CGLIB 代理: 在我看来,代理扩展了包装对象的实现,向其添加了额外的逻辑功能
像这样:
所以在我看来Spring使用第一种基于接口实现的代理(对吗?):
我认为在 AOP 中,额外的逻辑由 方法拦截器 的实现(是真的吗?)和标准逻辑由接口中定义的方法的实现来表示。
但是,如果前面的推理是正确的,我的疑惑是:为什么我需要定义这些接口并让对象包装的对象实现这些接口? (我无法理解代理本身是否实现了这些接口)。
为什么?具体如何运作?
Tnx
But what is the exact reason for which all these 3 interface are implemented?
如果代理没有实现所有这些接口,则无法将该 bean 连接到使用该接口的其他 bean(您会得到 ClassCastException)。例如,将该接口的所有 bean 自动装配到一个 bean 中。此外,如果代理没有实现接口,getBeanNamesForType 之类的东西将无法工作。
So it seems to me that exist 2 kinds of proxies (correct me if I am saying wrong assertions)
是的,没错。请参阅 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,它使用 Objenesis 来处理没有默认构造函数的子classing 目标。
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 的构造函数被调用两次:一次是在实例化动态生成的子 class 时(以创建代理),第二次是在创建实际 bean 时(目标)。
I think that in AOP the extra logic is represented by the implementation of the method interceptor (is it true?)
代理本质上只是调用需要应用的通知链。该建议并未在代理本身中实现。例如,@Transactional
的建议位于 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 代理。
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 将负责构建代理并确保它实现所有接口。
在你的图表中,你有 "Spring AOP Proxy (this)"。当您使用任何类型的代理时,您必须非常小心地使用 this
。
- 同一 class 内的调用不会应用建议,因为这些调用不会通过代理。
- 如果在您的一个 bean 中将
this
传递给一些外部代码,那么您传递的是 AOP 建议的目标。如果其他一些代码使用该引用,调用将不会应用 AOP 建议(同样,您正在绕过代理)。