春のサービスのオプションのネストされた注入

ZeAL0T:

インタフェースを考えるとIService、それの3つの実装:ServiceAServiceALoggerServiceAMetrics

ServiceALoggerそして、ServiceAMetricsのラッパーがあるServiceAと、必要に応じてインスタンス化されます。また組み合わせがあるServiceAMetricsServiceALoggerの両方がインスタンス。

私が使用してそれを実装する方法を知っている@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の間で循環依存関係を破壊するServiceAMetricsServiceALogger

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();
    }
}

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=209257&siteId=1