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

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

问题描述

我正在学习Spring,我有followig



考虑以下bean定义:

 < bean id =clientServiceclass =com.myapp.service.ClientServiceImpl/> 

现在考虑一下它被声明为一个切入点*的目标, * clientService bean。



还要考虑 ClientServiceImpl 实现3个接口



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



但是,实现所有这3个界面的确切原因是什么?



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


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


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


这样的一个例子:





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





我认为在 AOP 中,额外的逻辑是通过方法拦截器的实现来表示的它是真的吗?),标准逻辑由界面中定义的方法的实现来表示但是,如果以前的推理是正确的,我的怀疑是:为什么我需要定义这些接口,并且做对象包装的对象实现这些接口? (我不明白代理本身是否实现这些接口)。



为什么?如何工作?



Tnx

解决方案


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


如果代理没有实现所有这些接口,bean不能连接到使用该接口的其他bean(你会得到一个ClassCastException)。例如,将该界面的所有bean自动连接到一个bean中。另外,像 getBeanNamesForType 将不起作用。


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


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


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


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


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


y基本上只是调用需要应用的建议链。该建议在代理本身中没有实现。例如, @Transactional 的建议生活在 TransactionAspectSupport 。看看源代码 JdkDynamicAopProxy


,标准逻辑由
方法定义在接口中。


假设您正在编程接口并使用正确的JDK代理。 >


但是,如果以前的推理是正确的,我的疑惑是:为什么我需要
来定义这些接口,并且将包含的对象对象
实现这些接口? (我不明白代理本身是否
实现这些接口)。


如果要使用基于界面的代理你需要使用接口。只要确保所有的bean都实现了接口,那么所有的建议方法都是由这些接口定义的,而当一个bean依赖另一个bean时,该依赖关系是使用一个接口来指定的。 Spring将负责构建代理并确保它实现所有的接口。



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


  1. 同一课程内的通话不会提供建议,因为这些通话不会通过代理。

  2. 如果在你的一个bean中,将这个传递给一些外部代码,那么你传递了AOP建议的目标。如果一些其他代码使用该引用,则调用将不会应用AOP建议(再次,您绕过代理)。


I am studying Spring and I have the followig

Consider the following bean definition:

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

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

Consider also that the ClientServiceImpl class implements 3 interfaces

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 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.

  2. 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

Something like this:

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

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?

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)

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 Proxy: in wich, it seems to me that, the proxy extend the implementation of the wrapped object adding to it the extra logic features

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).

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

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.

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).

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.

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. 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天全站免登陆