我应该在哪里为Spring的@Qualifier注释定义常量?

时间:2019-09-09 10:28:45

标签: spring dependency-injection

Spring的依赖项注入允许使用@Qualifier("<flavor>")注释区分同一接口的多个实现。

例如,我们可以拥有:

public class Consumer {
  @Autowired("b") private SomeInterface dependency;
}

public interface SomeInterface { }

@Component @Qualifier("a")
public class VariantA implements SomeInterface { }

@Component @Qualifier("b")
public class VariantB implements SomeInterface { }

这要求使用者和实现都使用相同的常量字符串来标识变体,在此示例中为“ a”和“ b”。作为一个干净的编码器,我的第一个冲动是为这些字符串创建常量。

但是我应该把它们放在哪里?

A。消费者

将它们放入Consumer中是不可能的,因为这会将依赖关系转化为非法方向,从而要求实现了解其消费者:

public class Consumer {
  public final static String VARIANT_B = "b";
  @Autowired(Consumer.VARIANT_B) private SomeInterface dependency;
}

@Component @Qualifier(Consumer.VARIANT_B)
public class VariantB implements SomeInterface { }

B。实施

将它们放入实现中似乎也很重要,重新引入了依赖注入首先要删除的消费者知道的实现依赖:

public class Consumer {
  @Autowired(VariantB.VARIANT_B) private SomeInterface dependency;
}

@Component @Qualifier(VariantB.VARIANT_B)
public class VariantB implements SomeInterface {
  public final static String VARIANT_B = "b";
}

C。界面

将它们放在界面中似乎是一种选择,但是只有在界面是我的并且我可以自由更改的情况下才有可能。同样,事先让接口“知道”所有实现变体的想法听起来有些奇怪。

public class Consumer {
  @Autowired(SomeInterface.VARIANT_B) private SomeInterface dependency;
}

public interface SomeInterface {
  public final static String VARIANT_A = "a";
  public final static String VARIANT_B = "b";
}

@Component @Qualifier(SomeInterface.VARIANT_A)
public class VariantA implements SomeInterface { }

@Component @Qualifier(SomeInterface.VARIANT_B)
public class VariantB implements SomeInterface { }

D。常量类

最干净的解决方案似乎是将常量放入单独的开发对象中。这看起来有点开销,但是:

public class Consumer {
  @Autowired(ImplementationVariant.B) private SomeInterface dependency;
}

public interface SomeInterface { }

public class ImplementationVariant {
  public final static String A= "a";
  public final static String B= "b";
}

@Component @Qualifier(ImplementationVariant.A)
public class VariantA implements SomeInterface { }

@Component @Qualifier(ImplementationVariant.B)
public class VariantB implements SomeInterface { }

1 个答案:

答案 0 :(得分:0)

我会选择E:标准方式。

添加此间接标识以标识beans的名称会添加样板代码,这不是标准的(您的同行会感到惊讶)并且也不可靠。
为什么没有鲁棒性?限定词需要一个字符串,而不是一个有界的枚举值。这意味着您可以传递不正确的字符串,例如@Component @Qualifier(OtherImplementationVariant.B),并且仍然可以正常编译。

一个更健壮的替代方案是为拥有@Bean且具有@Qualifier的bean的@Bean方法工厂提供支持,并通过调用class YourPage extends StatefulWidget { @override _YourPageState createState() => _YourPageState(); } class _YourPageState extends State<YourPage> { double _maxHeight = 200, _minHeight = 44, _height = 44, _dividerHeight = 56, _offset = 19; int _maxLines = 1; static final Duration _fixDuration = Duration(milliseconds: 500); Duration _duration = _fixDuration; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: Padding( padding: const EdgeInsets.all(20), child: SizedBox( height: _maxHeight, child: Column( children: <Widget>[ AnimatedContainer( duration: _duration, height: _height, child: TextField( decoration: InputDecoration(hintText: "Enter a message"), maxLines: _maxLines, ), ), Container( height: _dividerHeight, width: 200, child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: <Widget>[ IconButton( icon: Icon(Icons.arrow_downward), onPressed: () { if (_height <= _maxHeight - _offset - _dividerHeight) { setState(() { _duration = _fixDuration; _height += _offset; _maxLines++; }); } }, ), GestureDetector( child: Icon(Icons.drag_handle), onPanUpdate: (details) { setState(() { _height += details.delta.dy; _duration = Duration.zero; // prevent overflow if height is more/less than available space var maxLimit = _maxHeight - _dividerHeight; var minLimit = 44.0; if (_height > maxLimit) _height = maxLimit; else if (_height < minLimit) _height = minLimit; _maxLines = 100; }); }, ), IconButton( icon: Icon(Icons.arrow_upward), onPressed: () { if (_height >= _minHeight + _offset) { setState(() { _duration = _fixDuration; _height -= _offset; }); } }, ), ], ), ) ], ), ), ), ); } } 方法来设置bean之间的依赖关系。但这仍然是冗长的,完全不是标准,无法将其概括为此类要求。所以也不是一个好主意。

因此,我认为您应该遵循标准,因为如果发生不匹配并且无法解决依赖关系,该问题将在Spring Boot启动后立即检测到