Why in Spring AOP the object are wrapped into a JD

2020-06-03 07:55发布

问题:

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

回答1:

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