Spring自动装配一个存根服务 - 重复的bean [英] Spring autowire a stubbed service - duplicate bean

查看:141
本文介绍了Spring自动装配一个存根服务 - 重复的bean的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

确定。我们需要@Autowire一个不同的Web服务(最好通过在网络服务器上切换JNDI设置),我对如何做到这一点感到茫然。这就是我接近问题的方式..

Ok. We have the need to @Autowire a different webservice on-the-fly (preferably by toggling a JNDI setting on the webserver) and I'm at a loss on how to do this. This is the way I was approaching the problems..

两个包:
com.mycomp.service.stub
com.mycomp.service。 impl

Two packages: com.mycomp.service.stub com.mycomp.service.impl

一个包包含MyServiceStub.java,而实现MyService
另一个包包含MyServiceImpl.java,它实现相同的

One package contains MyServiceStub.java while implement MyService The other package contains MyServiceImpl.java, which implements same

我的控制器,需要MyService,将bean定义为这样的

My controller, which requires MyService, has the bean defined as such

@Autowire
private MyService communicator;

我的spring-context.xml包含以下内容:

My spring-context.xml has the following:

<context:component-scan base-package="com.mycomp" />

此时我在自动装配期间遇到DuplicateBean异常。现在,我可以在spring-context.xml中静态定义要自动装配的bean:

At this point I get a DuplicateBean exception during autowiring. Now, I can statically define which bean to autowire in spring-context.xml:

<bean id="communicator" class="com.mycomp.service.impl.MyServiceImpl" />

一切正常......但是,如何翻转开关并切换到我们的QA服务器上的Stub方法?它与该服务没有任何关联,因此我们需要在启用存根的情况下运行。 JNDI属性最适合这个......但是我无法理解如何在运行时切换bean spring autowires。

and everything works fine... But then, how to 'flip' the switch and change over to the Stub method on our QA server? It has no connection to that service, so we need to run with stubs enabled. A JNDI property would be best for this.. but I just can't get my head around how to toggle what bean spring autowires at runtime.

任何帮助??

干杯,
Chris

Cheers, Chris

推荐答案

@Profile 解决方案



你一定要试试Spring 3.1 @Profile

@Profile solution

You definitely have to try Spring 3.1 @Profile:

@Autowire
private MyService communicator;

//...

@Service
@Profile("prd")
class MyServiceImpl //...

@Service
@Profile("qa")
class MyServiceStub //...

现在,根据启用的配置文件, DefaultMyService 将被初始化或 MyServiceStub

Now depending on which profile is enabled, either DefaultMyService will be initialized or MyServiceStub.

您可以通过各种方式选择个人资料:

You can choose between profile in various ways:

  • How to set active spring 3.1 environment profile via a properites file and not via an env variable or system property
  • using system property
  • programmatically
  • ...

在此示例中,方面分别包装每个 MyService 方法并返回存根值:

In this example the aspect wraps around every single MyService method separately and returns stubbed value:

@Aspect
@Service
public class StubAspect {

    @Around("execution(public * com.blogspot.nurkiewicz.MyService.foo(..))")
    public Object aroundFoo(ProceedingJoinPoint pjp) throws Throwable {
        if (stubMode()) {
            return //stub foo() result
        }
        return pjp.proceed();
    }

    @Around("execution(public * com.blogspot.nurkiewicz.MyService.bar(..))")
    public Object aroundBar(ProceedingJoinPoint pjp) throws Throwable {
        if (stubMode()) {
            return //stub bar() result
        }
        return pjp.proceed();
    }

    private boolean stubMode() {
        //whatever condition you want here
        return true;
    }

}

不幸的是,代码很简单返回值隐藏在方面内,您需要为每个目标方法单独的 @Around 。最后, MyServiceStub 没有地方。

The code is pretty straightforward, unfortunately the return values are buried inside the aspect and you need a separate @Around for every target method. Finally, there is no place for MyServiceStub.

@Aspect
@Service
public class StubAspect {

    private MyServiceStub stub = //obtain stub somehow

    @Around("execution(public * com.blogspot.nurkiewicz.MyService.*(..))")
    public Object aroundFoo(ProceedingJoinPoint pjp) throws Throwable {
        if (stubMode()) {
            MethodSignature signature = (MethodSignature)pjp.getSignature();
            Method method = signature.getMethod();
            return method.invoke(stub, pjp.getArgs());
        }
        return pjp.proceed();
    }

    private boolean stubMode() {
        //whatever condition you want here
        return true;
    }

}

这种方法更隐含,因为它自动包装每个目标方法,包括将来添加的新方法。这个想法很简单:如果 stubMode()关闭,请运行标准方法( pjp.proceed())。如果它是 - 运行完全相同的方法与完全相同的参数 - 但在不同的对象(在这种情况下为存根)。

This approach is more implicit as it automatically wraps every target method, including new methods added in the future. The idea is simple: if stubMode() is off, run the standard method (pjp.proceed()). If it is on - run the exact same method with exact same parameters - but on a different object (stub in this case).

这个解决方案更好,因为它涉及减少手动工作(以使用原始反射的代价)。

This solution is much better as it involves less manual work (at the price of using raw reflection).

注意,如果 MyService 实现都是Spring bean (即使用 @Primary 注释一个),你可能会遇到奇怪的麻烦。但它应该是一个良好的开端。

Note that if both MyService implementations are Spring beans (even when one is annotated with @Primary), you might run into weird troubles. But it should be a good start.

  • Spring 3.1 M1: Introducing @Profile

这篇关于Spring自动装配一个存根服务 - 重复的bean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆