Adding aspects on services across OSGi bundles
I have an OSGi bundle (that开发者_如何学运维 is not owned by me - so I cannot change it!) that exposes (exports) a service EchoService
, and I want to attach an aspect to methods of this service (so as to perform some pre/post processing around it). These are deployed on the Apache Felix container.
I've written my own OSGi bundle (that obviously imports the EchoService
), and attaches Spring aspects to it using standard Spring AOP. However, looks like the aspects are not attached and my interceptor is not being invoked.
I suspect that this is because I'm trying to intercept a service that does not belong to my bundle (which seems reasonable). Is that correct? How can I overcome this?
Here's what my interceptor/aspect looks like:
@Before("serviceOperation()")
public void before(JoinPoint jp) {
logger.debug("Entering method: " + jp.toShortString());
}
@AfterReturning("serviceOperation()")
public void after(JoinPoint jp) {
logger.debug("Exiting method: " + jp.toShortString());
}
I'm not an AOP nor a Spring expert, but maybe I could give you some ideas. As far as I see Spring use standard J2SE dynamic proxies for AOP proxies. Hence your clients should use the proxy instead of the original EchoService
object. This is also true when you're using CGLIB proxies because "the proxies are created by sub-classing the actual class".
If your client bundles asking for an EchoService
you have to pass them the proxy somehow. For this inside an OSGi container you should also export an EchoService
(proxy) and make sure that the clients use the proxied service/bundle, not the original. You can accomplish this by setting a different version number for the (proxied) package and set this version as an import requirement in your client bundles. (I suppose you can modify the clients of EchoService
.) For services you can set a property when you're registering it and modify the clients to query only for services which have this property.
If you are not able to modify the client bundles another solution could be wrapping the original bundle as an internal jar in your bundle. You can call the wrapped bundle's activator from your activator and pass them a modified BundleContext
. This BundleContext
should catch the registering service calls and register the proxy object instead of the original EchoService
. You can use simple delegate pattern since BundleContext
, ServiceListener
etc. are usually interfaces. I suppose it could work but it maybe has other challenges.
精彩评论