Статьи

Образец конфигурации bean-компонентов на основе Spring Scala

Последние несколько дней я использовал Spring Scala для игрушечного проекта, и должен сказать, что это фантастический проект, который еще больше упрощает настройку Spring по сравнению с уже простой конфигурацией, основанной исключительно на Spring Java Config .

Позвольте мне продемонстрировать это, начав с примера на основе Cake Pattern :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// =======================
// service interfaces
trait OnOffDeviceComponent {
  val onOff: OnOffDevice
  trait OnOffDevice {
    def on: Unit
    def off: Unit
  }
}
trait SensorDeviceComponent {
  val sensor: SensorDevice
  trait SensorDevice {
    def isCoffeePresent: Boolean
  }
}
 
// =======================
// service implementations
trait OnOffDeviceComponentImpl extends OnOffDeviceComponent {
  class Heater extends OnOffDevice {
    def on = println("heater.on")
    def off = println("heater.off")
  }
}
trait SensorDeviceComponentImpl extends SensorDeviceComponent {
  class PotSensor extends SensorDevice {
    def isCoffeePresent = true
  }
}
// =======================
// service declaring two dependencies that it wants injected
trait WarmerComponentImpl {
  this: SensorDeviceComponent with OnOffDeviceComponent =>
  class Warmer {
    def trigger = {
      if (sensor.isCoffeePresent) onOff.on
      else onOff.off
    }
  }
}
 
// =======================
// instantiate the services in a module
object ComponentRegistry extends
  OnOffDeviceComponentImpl with
  SensorDeviceComponentImpl with
  WarmerComponentImpl {
 
  val onOff = new Heater
  val sensor = new PotSensor
  val warmer = new Warmer
}
 
// =======================
val warmer = ComponentRegistry.warmer
warmer.trigger

Шаблон Cake — это чистый способ определения зависимостей в Scala.

Теперь, если бы нам нужно было указать эту зависимость с помощью нативной конфигурации Java Spring, но с языком Scala, позвольте мне сначала начать с компонентов, которые должны быть соединены вместе:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
trait SensorDevice {
    def isCoffeePresent: Boolean
  }
 
  class PotSensor extends SensorDevice {
    def isCoffeePresent = true
  }
 
  trait OnOffDevice {
    def on: Unit
    def off: Unit
  }
 
  class Heater extends OnOffDevice {
    def on = println("heater.on")
    def off = println("heater.off")
  }
 
  class Warmer(s: SensorDevice, o: OnOffDevice) {
    def trigger = {
      if (s.isCoffeePresent) o.on
      else o.off
    }
  }

и конфигурация, которая связывает эти компоненты вместе с образцом, который использует эту конфигурацию:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
import org.springframework.context.annotation.Configuration
  import org.springframework.context.annotation.Bean
 
  @Configuration
  class WarmerConfig {
    @Bean
    def heater(): OnOffDevice = new Heater
 
    @Bean
    def potSensor(): SensorDevice = new PotSensor
 
    @Bean
    def warmer() = new Warmer(potSensor(), heater())
  }
 
  import org.springframework.context.annotation.AnnotationConfigApplicationContext
 
  val ac = new AnnotationConfigApplicationContext(classOf[WarmerConfig])
 
  val warmer = ac.getBean("warmer", classOf[Warmer])
   
  warmer.trigger

В дальнейшем мы используем проект Spring-Scala для определения зависимостей, конфигурации и примера:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Bean
import org.springframework.scala.context.function.FunctionalConfiguration
 
 
class WarmerConfig extends FunctionalConfiguration {
  val h = bean("heater") {
    new Heater
  }
   
  val p = bean("potSensor") {
    new PotSensor
  }
   
  bean("warmer") {
    new Warmer(p(), h())
  }
}
 
import org.springframework.context.annotation.AnnotationConfigApplicationContext
import org.springframework.scala.context.function.FunctionalConfigApplicationContext
 
val ac = FunctionalConfigApplicationContext[WarmerConfig]
val warmer = ac.getBean("warmer", classOf[Warmer])
warmer.trigger

Суть проекта Spring Scala, описанного в этой вики, заключается в том, что метод «bean» происходит от черты «FunctionalConfiguration». Этот метод можно вызывать для создания bean-компонента, передавая параметры для указания, при необходимости, имени bean-компонента, псевдонима, область действия и функция, которая возвращает экземплярный компонент.
Надеемся, что этот пример дает хорошее представление о простоте Spring Java Config и о том, насколько проще проект Spring-Scala делает его для проектов на основе Scala.

Ссылка: Образец конфигурации bean-компонентов Spring Scala от нашего партнера JCG Биджу Кунджуммена из блога all and sundry.