gpt4 book ai didi

java - Spring 服务的可选嵌套注入(inject)

转载 作者:行者123 更新时间:2023-11-30 10:04:45 25 4
gpt4 key购买 nike

给定一个接口(interface) IService ,以及它的 3 个实现:ServiceA , ServiceALoggerServiceAMetrics .

ServiceALoggerServiceAMetricsServiceA 的包装器并将可选地实例化。此外还有一个组合 where 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();
}
}

最佳答案

看来我找到了可能的解决方案。这不是一个优雅的方法,但它确实有效。

我使用 @Priority 注释来确定当存在多个 bean 实例时应该注入(inject)哪个 bean。和 @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();
}
}

关于java - Spring 服务的可选嵌套注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55732607/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com