简体   繁体   中英

Spring framework and java like Object collectors In Scala

In Spring framework and Java world, there is an interesting object collector pattern that I use. For example consider below -

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
 }
}

Now this can easily injected in another class using 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
}

Now problem is I am not sure how same thing can be achieved in scala. I have done some search and found cake pattern ( http://loicdescotte.github.io/posts/scala-di/ ) used in scala but that didn't seem to achieve same thing as object collectors like above. I also want to follow open close principle which I think gets violated in cake pattern but using object collectors I can easily achieve it.

is there a way achieve same object collectors like implementation in scala?

There are templates in lighbend activator that illustration using spring DI on Play, Akka and Scala applications. Please see this: https://www.lightbend.com/activator/templates#filter:spring

I haven't used Spring as DI, I usually use Guice (explicitly used because it's default on play framework 2) and Implicits parameters both as a compilation DI.

Sample:

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)

Explicitly using java.util.List worked for me. This is not the prettiest solution but it shows that it basically works. Haven't tried that but implementing a corresponding PropertyEditor you could stick with the Scala types.

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
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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