跨 OSGi 包添加服务方面
我有一个 OSGi 包(不属于我 - 所以我无法更改它!),它公开(导出)服务 EchoService
,并且我想将一个方面附加到该服务的方法(因此以围绕它执行一些前/后处理)。它们部署在 Apache Felix 容器上。
我已经编写了自己的 OSGi 包(显然导入了 EchoService),并使用标准 Spring AOP 将 Spring 方面附加到它。但是,看起来这些方面没有附加,并且我的拦截器没有被调用。
我怀疑这是因为我试图拦截不属于我的捆绑包的服务(这似乎很合理)。这是正确的吗?我怎样才能克服这个问题?
这是我的拦截器/方面的样子:
@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 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());
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不是 AOP 也不是 Spring 专家,但也许我可以给你一些想法。据我所知 Spring 使用标准 J2SE 动态代理作为 AOP 代理。因此,您的客户 应该使用代理而不是原始的
EchoService
对象。当您使用 CGLIB 代理时也是如此,因为 “代理是通过对实际类进行子类化来创建的”。如果您的客户端捆绑请求
EchoService
,您必须以某种方式向它们传递代理。对于 OSGi 容器内的此操作,您还应该导出EchoService
(代理)并确保客户端使用代理服务/包,而不是原始服务/包。您可以通过为(代理)包设置不同的版本号并将该版本设置为客户端捆绑包中的导入要求来实现此目的。 (我想您可以修改 EchoService 的客户端。)对于服务,您可以在注册时设置一个属性,并修改客户端以仅查询具有此属性的服务。如果您无法修改客户端捆绑包,另一种解决方案可能是将原始捆绑包包装为捆绑包中的内部 jar。您可以从激活器中调用打包包的激活器,并向它们传递修改后的
BundleContext
。此BundleContext
应捕获注册服务调用并注册代理对象,而不是原始EchoService
。您可以使用简单的委托模式,因为BundleContext
、ServiceListener
等通常是接口。我认为它可以发挥作用,但可能还有其他挑战。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 anEchoService
(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 ofEchoService
.) 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
. ThisBundleContext
should catch the registering service calls and register the proxy object instead of the originalEchoService
. You can use simple delegate pattern sinceBundleContext
,ServiceListener
etc. are usually interfaces. I suppose it could work but it maybe has other challenges.