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”。作为一个干净的编码器,我的第一个冲动是为这些字符串创建常量。
但是我应该把它们放在哪里?
将它们放入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 { }
将它们放入实现中似乎也很重要,重新引入了依赖注入首先要删除的消费者知道的实现依赖:
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";
}
将它们放在界面中似乎是一种选择,但是只有在界面是我的并且我可以自由更改的情况下才有可能。同样,事先让接口“知道”所有实现变体的想法听起来有些奇怪。
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 { }
最干净的解决方案似乎是将常量放入单独的开发对象中。这看起来有点开销,但是:
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 { }
答案 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启动后立即检测到。