简体   繁体   English

依赖注入,Scala和Spring

[英]Dependency injection, Scala and Spring

I love the concept of DI and loosely coupled system, a lot. 我喜欢DI和松散耦合系统的概念,很多。 However, I found tooling in Spring lacking at best. 但是,我发现Spring中的工具最多缺乏。 For example, it's hard to do "refactoring", eg to change a name of a bean declared in Spring. 例如,很难进行“重构”,例如更改Spring中声明的bean的名称。 I'm new to Spring, so I would be missing something. 我是Spring的新手,所以我会遗漏一些东西。 There is no compiling time check etc. 没有编译时间检查等。

My question is why do we want to use XML to store the configuration? 我的问题是为什么我们要使用XML来存储配置? IMO, the whole idea of Spring (IoC part) is to force certain creational pattern. IMO,Spring(IoC部分)的整个想法是强制某些创造模式。 In the world of gang-of-four patterns, design patterns are informative. 在四人一组模式的世界中,设计模式是信息性的。 Spring (and other DIs) on the other hand, provides very prescribed way how an application should be hooked up with individual components. 另一方面,Spring(和其他DI)提供了一种非常规定的方式,即如何将应用程序与各个组件连接起来。

I have put Scala in the title as well as I'm learning it. 我已经把Scala放在标题中以及我正在学习它。 How do you guys think to create a domain language (something like the actor library) for dependency ingestion. 你们怎么想创建一个领域语言(比如演员库)来依赖摄取。 Writing the actual injection code in Scala itself, you get all the goodies and tooling that comes with it. 在Scala中编写实际的注入代码,您将获得随附的所有好东西和工具。 Although application developers might as well bypass your framework, I would think it's relatively easy to standard, such as the main web site/app will only load components of certain pattern. 虽然应用程序开发人员可能会绕过您的框架,但我认为标准相对容易,例如主网站/应用程序只会加载某些模式的组件。

There's a good article on using Scala together with Spring and Hibernate here . 有使用斯卡拉连同Spring和Hibernate的好文章在这里

About your question: you actually can use annotations. 关于你的问题:你实际上可以使用注释。 It has some advantages. 它有一些优点。 XML, in turn, is good beacause you don't need to recompile files, that contain your injection configs. 反过来,XML很好,因为你不需要重新编译包含注射配置的文件。

There is an ongoing debate if Scala needs DI. 如果Scala 需要 DI,那就一直在争论。 There are several ways to "do it yourself", but often this easy setup is sufficient: 有几种方法可以“自己动手”,但通常这种简单的设置就足够了:

//the class that needs injection
abstract class Foo {
  val injectMe:String
  def hello = println("Hello " + injectMe)
}

//The "binding module"
trait Binder {
  def createFooInstance:Foo
}

object BinderImpl extends Binder {
  trait FooInjector {
    val injectMe = "DI!"   
  }

  def createFooInstance:Foo = new Foo with FooInjector
}

//The client
val binder:Binder = getSomehowTheRightBinderImpl  //one way would be a ServiceLoader
val foo = binder.createFooInstance
foo.hello
//--> Hello DI!

For other versions, look here for example. 对于其他版本,请查看此处

There are different approaches to DI in java, and not all of them are necessarily based on xml. 在Java中有不同的DI方法,并非所有方法都必须基于xml。

Spring 弹簧

Spring provides a complete container implementation and integration with many services (transactions, jndi, persistence, datasources, mvc, scheduling,...) and can actually be better defined using java annotations. Spring提供了一个完整的容器实现,并与许多服务(事务,jndi,持久性,数据源,mvc,调度......等)集成,实际上可以使用java注释更好地定义。

Its popularity stems from the number of services that the platform integrates, other than DI (many people use it as an alternative to Java EE , which is actually following spring path starting from its 5 edition). 它的受欢迎程度源于平台集成的服务数量,而不是DI (许多人将其用作Java EE的替代品,实际上是从第5版开始沿着弹簧路径开始)。

XML was the original choice for spring , because it was the de-facto java configuration standard when the framework came to be. XML是spring的最初选择,因为它是框架实现时事实上的java配置标准。 Annotations is the popular choice right now. 注释是目前流行的选择。

As a personal aside, conceptually I'm not a huge fan of annotation-based DI , for me it creates a tight coupling of configuration and code, thus defeating the underlying original purpose of DI . 作为个人而言,从概念上讲,我不是基于注释的DI的忠实粉丝,对我而言,它创建了配置和代码的紧密耦合,从而挫败了DI的潜在原始目的。

There are other DI implementation around that support alternative configuration declaration: AFAIK Google Guice is one of those allowing for programmatic configuration as well. 还有其他DI实现支持替代配置声明:AFAIK Google Guice也是允许编程配置的其中之一。


DI and Scala DI和斯卡拉

There are alternative solutions for DI in scala, in addition to using the known java frameworks (which as far as I know integrate fairly well). 除了使用已知的java框架(据我所知,它集成得相当好)之外,还有scala中DI的替代解决方案。

For me the most interesting that maintain a familiar approach to java is subcut . 对我来说,保持熟悉的java方法最有趣的是subcut

It strikes a nice balance between google guice and one of the most well-known DI patterns allowed by the specific design of the scala language: the Cake Pattern . 它在谷歌guice和scala语言的特定设计所允许的最着名的DI模式之一之间取得了很好的平衡: 蛋糕模式 You can find many blog posts and videos about this pattern with a google search . 您可以使用Google搜索找到有关此模式的许多博文和视频。

Another solution available in scala is using the Reader Monad , which is already an established pattern for dynamic configuration in Haskell and is explained fairly well in this video from NE Scala Symposium 2012 and in this video and related slides . scala中提供的另一个解决方案是使用Reader Monad ,它已经是Haskell中动态配置的既定模式,并且在此视频中从NE Scala Symposium 2012以及此视频和相关幻灯片中得到了相当好的解释。

The latter choice goes with the warning that it involves a decent level of familiarity with the concept of Monads in general and in scala, and often aroused some debate around its conceptual complexity and practical usefulness. 后一种选择伴随着警告,它涉及对Monads概念和scala的理解程度,并经常引起关于其概念复杂性和实际用途的一些争论。 This related thread on the scala-debate ML can be quite useful to have a better grip on the subject. 关于scala-辩论ML的这个相关主题对于更好地掌握这个主题非常有用。

I love the concept of DI and loosely coupled system, a lot. 我喜欢DI和松散耦合系统的概念,很多。 However, I found tooling in Spring lacking at best. 但是,我发现Spring中的工具最多缺乏。 For example, it's hard to do "refactoring", eg to change a name of a bean declared in Spring. 例如,很难进行“重构”,例如更改Spring中声明的bean的名称。 I'm new to Spring, so I would be missing something. 我是Spring的新手,所以我会遗漏一些东西。 There is no compiling time check etc. 没有编译时间检查等。

You need a smarter IDE. 您需要一个更智能的IDE。 IntelliJ from JetBrains allows refactoring, renaming, etc. with full knowledge of your Spring configuration and your classes. JetBrains的IntelliJ允许重构,重命名等,并充分了解您的Spring配置和类。

My question is why do we want to use XML to store the configuration? 我的问题是为什么我们要使用XML来存储配置?

Why not? 为什么不? You have to put it somewhere. 你必须把它放在某个地方。 Now you have a choice: XML or annotations. 现在您可以选择:XML或注释。

IMO, the whole idea of Spring (IoC part) is to force certain creational pattern. IMO,Spring(IoC部分)的整个想法是强制某些创造模式。 In the world of gang-of-four patterns, design patterns are informative. 在四人一组模式的世界中,设计模式是信息性的。

ApplicationContext is nothing more than a big object factory/builder. ApplicationContext只不过是一个大对象工厂/构建器。 That's a GoF pattern. 这是一个GoF模式。

Spring (and other DIs) on the other hand, provides very prescribed way how an application should be hooked up with individual components. 另一方面,Spring(和其他DI)提供了一种非常规定的方式,即如何将应用程序与各个组件连接起来。

GoF is even more prescriptive: You have to build it into objects or externalize it into configuration. GoF更具说明性:您必须将其构建为对象或将其外部化为配置。 Spring externalizes it. Spring将其外化。

I have put Scala in the title as well as I'm learning it. 我已经把Scala放在标题中以及我正在学习它。 How do you guys think to create a domain language (something like the actor library) for dependency ingestion. 你们怎么想创建一个领域语言(比如演员库)来依赖摄取。

You must mean "injection". 你必须指的是“注射”。

Writing the actual injection code in Scala itself, you get all the goodies and tooling that comes with it. 在Scala中编写实际的注入代码,您将获得随附的所有好东西和工具。

Don't see what that will buy me over and above what Spring gives me now. 不要看到春天给我的东西会超过什么。

Although application developers might as well bypass your framework, I would think it's relatively easy to standard, such as the main web site/app will only load components of certain pattern. 虽然应用程序开发人员可能会绕过您的框架,但我认为标准相对容易,例如主网站/应用程序只会加载某些模式的组件。

Sorry, I'm not buying your idea. 对不起,我不是在买你的想法。 I'd rather use Spring. 我宁愿用Spring。

But there's no reason why you shouldn't try it and see if you can become more successful than Spring. 但是没有理由你不应该尝试它,看看你是否能比Spring更成功。 Let us know how you do. 让我们知道你是怎么做的。

I cannot agree that XML is problem in Java and Spring: I use Spring and Java extensively without to much XML because most configuration is done with annotations (type and name is powerful contract) - it looks really nice. 我不能同意XML在Java和Spring中是一个问题:我使用Spring和Java而不需要太多XML,因为大多数配置都是使用注释完成的(类型和名称是强大的契约) - 它看起来非常好。 Only for 10% cases I use XML because it is easier to do it in XML than code special solution with factories / new classes / annotations. 仅在10%的情况下我使用XML,因为在XML中比使用工厂/新类/注释的代码特殊解决方案更容易。 This approach was inspired by Guice and Spring from 3.0 implements its as JSR-330 (but even that I use Spring 2.5 with spring factory configured with JSR-330 annotations instead of default spring-specific @Autowired). 这种方法受到Guice的启发,而Spring从3.0实现了它作为JSR-330(但即使我使用Spring 2.5配置弹簧工厂配置JSR-330注释而不是默认的特定于Spring的@Autowired)。

Probably scala can provide better syntax for developing in DI style and I'm looking at it now (pointed Cake Pattern). 可能scala可以提供更好的语法来开发DI风格,我现在正在看它(尖头蛋糕模式)。

i can't really comment on scala, but DI helps enforce loose coupling. 我无法评论scala,但DI有助于强制松散耦合。 It makes refactoring large apps soooo much easier. 它使重构大型应用程序变得更容易。 If you don't like a component, just swap it out. 如果您不喜欢某个组件,只需将其换掉即可。 Need another implementation for a particular environment, easy just plug in a new component. 需要针对特定​​环境的其他实现,只需插入新组件即可。

I agree! 我同意! To me he way most people use Spring is a mild version of hell. 对我而言,大多数人使用Spring是一种温和的地狱版本。

When you look at the standard Springified code there are interfaces everywhere, and you never really know what class is used to implement an interface. 当您查看标准的Springified代码时,到处都有接口,并且您从未真正知道用于实现接口的类。 You have to look into some fantastic configuration to find that out. 您必须查看一些出色的配置才能找到答案。 Easy read = not. 易读=不。 To make this code surfable you need a very advanced IDE, like Intelly J. 要使这个代码可以浏览,你需要一个非常先进的IDE,比如Intelly J.

How did we end up in this mess? 我们怎么在这个烂摊子里结束了? I blame automated unit testing! 我责怪自动化单元测试! If you want to connect mocks to each and every class you can not have dependencies. 如果要将mocks连接到每个类,则不能具有依赖关系。 If it wasn't for unit testing we could probable do just as well without loose coupling, since we do not want the customer to replace single classes willy nilly in our Jars. 如果它不是用于单元测试,我们很可能在没有松散耦合的情况下也可以这样做,因为我们不希望客户在我们的罐子里无法替换单个类。

In Scala you can use patterns, like the "Cake Patten" to implement DI without a framework. 在Scala中,您可以使用模式,例如“Cake Patten”来实现没有框架的DI。 You can also use structural typing to do this. 您也可以使用结构类型来执行此操作。 The result is still messy compared to the original code. 与原始代码相比,结果仍然很混乱。

Personally I think one should consider doing automated testing on modules instead of classes to escape this mess, and use DI to decouple entire modules. 我个人认为应该考虑对模块进行自动化测试而不是类来逃避这种混乱,并使用DI来解耦整个模块。 This strategy is by definition not unit testing. 根据定义,该策略不是单元测试。 I think most of the logic lies in the actual connections between classes, so IMHO one will benefit more from module testing than unit testing. 我认为大多数逻辑都在于类之间的实际连接,因此恕我直言的模块测试比单元测试更有益。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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