#spring #scala #cake-pattern
#spring #scala #шаблон для торта
Вопрос:
В Spring framework и Java world есть интересный шаблон сборщика объектов, который я использую. Например, рассмотрим ниже —
public interface Calculator {
SomeOutput calculate(SomeInput input);
}
@Component
public class CalImpl1 implements Calculator {
public SomeOutput calculate(SomeInput input){
//some implementation
}
}
@Component
public class CalImpl2 implements Calculator {
public SomeOutput calculate(SomeInput input){
//some implementation
}
}
Теперь это можно легко внедрить в другой класс, используя Spring DI
@Component
public class Main {
//This line collects all to implementors of this and set it here.
@Autowired
public List<Calculator> calculators;
//other methods
}
Теперь проблема в том, что я не уверен, как то же самое можно достичь в scala. Я провел некоторый поиск и нашел шаблон cake (http://loicdescotte.github.io/posts/scala-di /) используется в scala, но, похоже, это не дает того же результата, что и сборщики объектов, как описано выше. Я также хочу следовать принципу open close, который, я думаю, нарушается в шаблоне cake, но, используя сборщики объектов, я могу легко достичь этого.
есть ли способ добиться таких же сборщиков объектов, как реализация в scala?
Комментарии:
1. Это скорее особенность контейнера DI, чем общий шаблон. т. Е. Автоматическое подключение, когда встречается список, рассмотрит возможность введения нескольких совпадающих компонентов. Если вы не предоставите нам больше информации о том, какой контейнер DI вы используете в Scala, практически невозможно дать соответствующий и значимый ответ. Учитывая, что вы можете использовать Spring с Scala, я думаю, что то, чего вы хотите достичь, все равно будет работать, если вы используете Spring в своем проекте Scala
2. Я могу использовать абсолютно любой фреймворк, который позволяет мне достичь того же в scala.
3. Итак, учитывая, что Spring работает со Scala, я считаю, что такое поведение при внедрении все равно должно быть доступно, так в чем причина, по которой оно не используется или как оно не работает?
4. Тот же пример, что и выше, не работает для scala (после настройки небольших синтаксисов scala и использования trait вместо интерфейса и т. Д.).
5. Не знаком с Scala, просто хочу знать, работает ли это, если есть только 1
Calculator
компонент, и вы подключаете aCalculator
вместоList<Calculator>
? Потому что я считаю, что это поведение Spring, которое не должно зависеть от языка (при условии, что сгенерированный код эквивалентен Java с 1. компоненты реализуютCalculator
интерфейс 2.@Autowired
поле имеет типList
с правильным параметром типа.
Ответ №1:
В lighbend activator есть шаблоны, иллюстрирующие использование spring DI в приложениях Play, Akka и Scala. Пожалуйста, посмотрите это: https://www.lightbend.com/activator/templates#filter:spring
Я не использовал Spring в качестве DI, я обычно использую Guice (явно используется, потому что он используется по умолчанию в play framework 2) и подразумевает параметры как для компиляции DI.
Пример:
class B
class X(x: Int)(implicit c: B)
//DI - mostly define in main method/application
implicit val c: B = new B
val x = new X(2)
Ответ №2:
Явное использование java.util.List
сработало для меня. Это не самое красивое решение, но оно показывает, что оно в основном работает. Не пробовал этого, но, реализуя соответствующий PropertyEditor
, вы могли бы придерживаться типов Scala.
trait Calculator {
def calculate(input: SomeInput) : SomeOutput
}
@Component
class CalImpl1 extends Calculator {
override def calculate(input: SomeInput): SomeOutput = ...
}
@Component
class CalImpl2 extends Calculator {
override def calculate(input: SomeInput): SomeOutput = ...
}
@Component
class Main @Autowired()(calculators: java.util.List[Calculator]) {
// or inject field if constructor injection is not desired
// @Autowired
// var calculators: java.util.List[Calculator] = _
}
object Main {
def main(args: Array[String]) = {
val ctx = new AnnotationConfigApplicationContext("your package name here")
val main = ctx.getBean(classOf[Main])
// calculators should now be wired in the returned instance
}
}
Комментарии:
1. вы пробовали этот пример в работе? Я не уверен, работает ли это.
2. Да, работает для меня. Просто обновил код, добавив небольшой метод main. Запуская его как отдельное приложение, я получаю
Main
экземпляр, которыйcalculators
правильно подключен. Также заменено@Inject
на@Autowired
. Не имеет никакого значения, но, возможно, был какой-то источник путаницы?