Spring AutoWire с заглушкой обслуживания - дубликат бобов - PullRequest
4 голосов
/ 26 января 2012

Хорошо. Нам нужно @Autowire другой веб-сервис на лету (предпочтительно путем переключения настроек JNDI на веб-сервере), и я не знаю, как это сделать. Вот так я подходил к проблемам ..

Два пакета: com.mycomp.service.stub com.mycomp.service.impl

Один пакет содержит MyServiceStub.java при реализации MyService. Другой пакет содержит MyServiceImpl.java, который реализует тот же

Мой контроллер, для которого требуется MyService, имеет компонент, определенный как

@Autowire
private MyService communicator;

В моем файле spring-context.xml есть следующее:

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

В этот момент я получаю исключение DuplicateBean во время автоматической проводки. Теперь я могу статически определить, какой bean-компонент будет автоматически подключен в spring-context.xml:

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

и все работает нормально ... Но тогда, как «переключить» коммутатор и перейти на метод Stub на нашем сервере QA? Он не имеет связи с этой службой, поэтому нам нужно работать с включенными заглушками. Для этого лучше всего подойдет свойство JNDI ... но я просто не могу разобраться, как переключать автопровода бобовых пружин во время выполнения.

Любая помощь ??

Ура, Chris

Ответы [ 2 ]

5 голосов
/ 26 января 2012

@Profile решение

Вы обязательно должны попробовать Spring 3.1 @Profile:

@Autowire
private MyService communicator;

//...

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

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

Теперь, в зависимости от того, какой профиль включен, либо DefaultMyService будет инициализирован или MyServiceStub.

Вы можете выбирать между профилями различными способами:

Spring AOP (явно для каждогоmethod)

В этом примере аспект оборачивается вокруг каждого отдельного метода MyService отдельно и возвращает значение-заглушку:

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

Spring AOP (автоматически для всех методов)

@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()).Если он включен - запустите точно такой же метод с точно такими же параметрами - но на другом объекте (в данном случае заглушку).

Это решение намного лучше, так как требует меньше ручной работы (за счет использованиянеобработанное отражение).

Обратите внимание, что если обе реализации MyService являются компонентами Spring (даже если одна из них помечена @Primary), вы можете столкнуться со странными проблемами.Но это должно быть хорошим началом.

См. Также:

0 голосов
/ 26 января 2012

Возможно, вы можете заменить класс свойством и развернуть свое приложение с другими файлами свойств.Производственная версия будет содержать имя реального класса, в то время как версия QA будет содержать имя заглушки.

Может быть, это http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-factory-extension-factory-postprocessors может вам помочь.

...