繁体   English   中英

为什么在Spring AOP中,对象被包装到实现接口的JDK代理中?

[英]Why in Spring AOP the object are wrapped into a JDK proxy that implements interfaces?

我正在学习春天,我有跟随

考虑以下bean定义:

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

现在考虑一下它被声明为切入点*的情况,目标是** clientService bean中的所有方法

还要考虑ClientServiceImpl实现3个接口

现在我知道使用AOP 会对clientService bean进行代理,并且该代理实现所有3个接口。

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

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

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

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

像这样的东西:

在此输入图像描述

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

在此输入图像描述

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

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

为什么? 究竟如何运作?

TNX

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

如果代理没有实现所有这些接口,则无法将bean连接到使用该接口的其他bean(您将获得ClassCastException)。 例如,将该接口的所有bean自动装配到bean中。 此外,如果代理未实现接口,则getBeanNamesForType内容将无法工作。

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

对,那是正确的。 请参阅ScopedProxyMode 默认情况下,Spring不会创建代理。 如果需要包装bean以添加其他行为(AOP),它只会创建一个代理。 请注意,还有一个基于CGLIB的代理的特例,它使用Objenesis来处理没有默认构造函数的子类化目标。

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

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

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

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

标准逻辑由接口中定义的方法的实现表示。

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

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

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

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

  1. 同一类中的调用将不会应用建议,因为这些调用不会通过代理。
  2. 如果你的bean中的一个你通过this一些外部的代码,你传递了AOP通知的目标。 如果某些其他代码使用该引用,则调用将不会应用AOP建议(再次,您绕过代理)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM