@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
), вы можете столкнуться со странными проблемами.Но это должно быть хорошим началом.
См. Также: