简体   繁体   English

根据@qualifier名称生成spring bean

[英]Generate spring beans based on @qualifier names

Is it possible to create beans based on the value in Qualifier? 是否可以基于Qualifier中的值创建bean? I'm looking to be able to just mark Micrometer Counters/Gauges/etc... with a Qualifier containing the metric name. 我希望能够仅使用包含度量标准名称的限定符来标记千分尺/量规/等。

@Autowired
@Qualifer("my.service.my.metric") Counter metric;

spring would give me: 春天会给我:

metricRegister.counter("my.service.my.metric")

My google-fu is failing me and I don't see an obvious way of doing what I want. 我的Google Fu令我失望,而且我看不到一种明显的方式来做我想做的事。

edit more context: I'm just trying to get rid of the logic that happens in the constructor, and avoid Config boiler plate for each metric 编辑更多上下文:我只是想摆脱构造函数中发生的逻辑,并避免为每个指标配置Config样板

Current Way: 当前方式:

@Service
class MyService {

  private Counter counter1;
  private Counter counter2;

  MyService(MeterRegistry registry) {
     this.counter1 = registry.counter("someMetric");
     this.counter2 = registry.counter("otherMetric");
  }
}

What I would like to work with a some sort of specialized beanFactory that sees the value/name in the Qualifier 我想与某种专用BeanFactory一起工作的东西,它可以在Qualifier中看到值/名称

@Service
class MyService {
  private Counter counter1;
  private Counter counter2;

  MyService(@Qualifer("someMetric") Counter counter1, @Qualifier("otherMetric") Counter counter2) {
    this.counter1 = counter1;
    this.counter2 = counter2;
  }
}

(I'll actually be using lombok for the constructer generation so I wouldn't even have a visible constructor) (实际上,我将在生成器生成器中使用lombok,因此我什至没有可见的构造器)

You need to create your class with a qualifier name like: @Component("clsA") public class classA 您需要使用如下限定词来创建您的类:@Component(“ clsA”)public class classA

and pass 'clsA' has a qualifier name 并通过“ clsA”具有限定词名称

You need to giver your Bean/Component a name: 您需要给Bean/Component一个名字:

import org.springframework.stereotype.Component;

@Component("my.service.my.metric")
public class Counter {
    // Code
}

And after that you will be able to use: 之后,您将可以使用:

@Autowired
@Qualifer("my.service.my.metric") 
Counter metric;

As mentioned in the Spring docs about the value that you are passing to the @Component 如Spring文档中所述,关于您传递给@Component

The value may indicate a suggestion for a logical component name, to be turned into a Spring bean in case of an autodetected component. 该值可能表明建议使用逻辑组件名称,以在自动检测到组件的情况下将其转换为Spring bean。 @return the suggested component name, if any (or empty String otherwise) @返回建议的组件名称(如果有)(否则返回空字符串)

I think what you need is a configuration class. 我认为您需要的是配置类。

@Configuration
class MetricConfiguration {
    public static final String METRIC_1_NAME = "your.metric.name";
    public static final String METRIC_2_NAME = "your.other.metric.name";

    @Bean(METRIC_1_NAME)
    public Counter(MetricsRegistry registry) {
        return registry.counter(METRIC_1_NAME, counter);
    }

    @Bean(METRIC_2_NAME)
    public Counter(MetricsRegistry registry) {
        return registry.counter(METRIC_2_NAME, counter);
    }
}

Then you can inject them via 然后您可以通过注入

@Service
class YourService {
    @Autowired
    @Qualifier(MetricConfiguration.METRIC_1_NAME)
    Counter metric1Counter;
}

@Service
class YourOtherService {
    @Autowired
    @Qualifier(MetricConfiguration.METRIC_2_NAME)
    Counter metric2Counter;
}

Not exactly what you ask for, but I don't see how this is not equivalent. 并非完全是您要的,但我看不出这有什么不同。

Provide a factory bean 提供工厂豆

@Service public class CounterFactory {
    @Autowired private MeterRegistry registry;

    // cache already created counters; you could also use Spring's caching
    Map<String, Counter> createdCounters = new HashMap<>();

    public Counter createCounter(String metricName) {
        return createdCounters.computeIfAbsent(metricName, s -> registry.counter(s));
    }
}

Now you can NOT get Counter beans by using 现在,你不能 Counter用豆

@Service public class CounterClient {
    private static final String METRIC_NAME = "my_metric_name";
    @Autowired @Qualifier(METRIC_NAME)
    private Counter metric;

    public void triggerMetric() { metric.inc(); }
}

but like this which I think is just as good. 但是我觉得这样也一样。

@Service public class CounterClient {
    private static final String METRIC_NAME = "my_metric_name";
    private Counter metric;

    CounterClient(CounterFactory factory) {
        metric = factory.createCounter(METRIC_NAME);
    }

    public void triggerMetric() { metric.inc(); }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM