ZeAL0T:
インタフェースを考えるとIService
、それの3つの実装:ServiceA
、ServiceALogger
とServiceAMetrics
。
ServiceALogger
そして、ServiceAMetrics
のラッパーがあるServiceA
と、必要に応じてインスタンス化されます。また組み合わせがあるServiceAMetrics
とServiceALogger
の両方がインスタンス。
私が使用してそれを実装する方法を知っている@Configuration
と@Bean
方法が、それは(クラスの注釈使用して実施することが可能ですか@Primary
、@Order
...)?
ここでは概念を実証するためのスニペットは次のとおりです。
package com.foo;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.stereotype.Service;
interface IService {
void foo();
}
class LoggerCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return false;
}
}
class MetricsCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return false;
}
}
@Service
class ServiceA implements IService {
@Override
public void foo() {
System.out.println("I'm foo");
}
}
@Service
@Conditional(LoggerCondition.class)
class ServiceALogger implements IService {
private final IService service;
public ServiceALogger(IService service) {
this.service = service;
}
@Override
public void foo() {
System.out.println("print some logs");
service.foo();
}
}
@Service
@Conditional(MetricsCondition.class)
class ServiceAMetrics implements IService {
private final IService service;
public ServiceAMetrics(IService service) {
this.service = service;
}
@Override
public void foo() {
System.out.println("send some metrics");
service.foo();
}
}
@Configuration
@ComponentScan("com.foo")
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(Main.class);
ctx.refresh();
IService bean = ctx.getBean(IService.class);
bean.foo();
}
}
ZeAL0T:
私のように見えるが可能な解決策を見つけました。これは、エレガントなものではないが、それは動作します。
私が使用し@Priority
、それらのいくつかのインスタンスがある場合に注入されるべきか豆を決定するために注釈を。そして、@Qualifier
の間で循環依存関係を破壊するServiceAMetrics
とServiceALogger
。
package com.foo;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.stereotype.Service;
import javax.annotation.Priority;
import java.util.List;
interface IService {
void foo();
}
class LoggerCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return true;
}
}
class MetricsCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return true;
}
}
@Service
@Qualifier("main")
@Priority(Integer.MAX_VALUE)
class ServiceA implements IService {
@Override
public void foo() {
System.out.println("I'm foo");
}
}
@Service
@Conditional(LoggerCondition.class)
@Priority(Integer.MAX_VALUE - 1)
class ServiceALogger implements IService {
private final IService service;
// using this @Qualifier prevents circular dependency
public ServiceALogger(@Qualifier("main") IService service) {
this.service = service;
}
@Override
public void foo() {
System.out.println("print some logs");
service.foo();
}
}
@Service
@Conditional(MetricsCondition.class)
@Priority(Integer.MAX_VALUE - 2)
class ServiceAMetrics implements IService {
private final IService service;
public ServiceAMetrics(IService service) {
this.service = service;
}
@Override
public void foo() {
System.out.println("send some metrics");
service.foo();
}
}
@Configuration
@ComponentScan("com.foo")
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(Main.class);
ctx.refresh();
IService bean = ctx.getBean(IService.class);
bean.foo();
}
}