无论如何,这是关于我的背景和我的一些东西。 app:
从事Java一段时间开发,从事后端Web开发。是的,我进行了大量的单元测试。为了实现这一点,我通常制作(至少)一种方法的两个版本:一个使用实例变量,一个仅使用传递给该方法的变量。使用实例变量的一个调用另一个,提供实例变量。当进行单元测试时,我使用Mockito模拟对象,然后调用不使用实例变量的方法。这就是我一直以来所理解的“依赖注入”。
从CS的角度来看,我的应用程序非常简单。小型项目,最初需要1-2个开发人员。通常是CRUD类型的操作,会进行一堆搜索。基本上是一堆RESTful Web服务,再加上一个Web前端,最后是一些移动客户端。我正在考虑使用直接的HTML / CSS / JS / JQuery进行前端,因此没有真正的计划使用JSP。使用Hibernate作为ORM,并使用Jersey来实现Web服务。
我已经开始编码,并且真的很想在那里进行演示,我可以四处逛逛,看看是否有人想投资。因此,显然时间至关重要。我了解到Spring具有相当的学习曲线,而且看起来它需要一堆XML配置,而我通常会尽量避免这种困扰。但是,如果它可以使我的生活更轻松,并且(尤其是)可以使我的生活和开发速度更快,那么我愿意忍痛学习Spring。
所以请。教我我应该使用Spring吗?为什么或为什么不呢?
#1 楼
Spring框架做什么?我应该使用它吗?为什么或为什么不呢?
Spring是一个框架,可以帮助您将不同的组件“连接”在一起。如果您有很多组件,并且您可能决定以不同的方式组合它们,或者希望根据不同的设置或环境轻松地将一个组件替换为另一个组件,则它非常有用。
这就是我一直以来所理解的“依赖注入”。
我建议使用不同的定义:
“设计您的对象,以便它们依靠外部力量为他们提供所需的东西,并期望在任何人要求他们开始执行其通常的工作之前始终注入这些依赖项。”
将其与:“每个对象都有责任去寻找它启动时需要的所有东西。”
看起来它需要一堆XML配置
好吧,大多数XML(或基于注释)的东西都在告诉Spring东西,例如:
当有人要求“ HammerStore”时,我希望您创建一个
example.HammerStore
的实例并返回。下次缓存该实例,因为只需要一个商店。当有人问“ SomeHammer”时,我想让你问一个“ HammerStore”,并返回商店的
makeHammer()
方法的结果。不要缓存此结果。当有人要求“ SomeWrench”时,我希望您创建
example.WrenchImpl
的实例,使用配置设置gaugeAmount
并将其放入实例的setWrenchSize()
属性中。不要缓存结果。当有人问“ LocalPlumber”时,我想创建一个
example.PlumberImpl
的实例。将字符串“ Pedro”放入其setName()
方法中,将“ SomeHammer”放入其setHammer()
方法中,并将“ SomeWrench”放入其setWrench()
方法中。返回结果,并缓存结果供以后使用,因为我们只需要一名水管工。通过这种方式,Spring允许您连接组件,对其进行标记,控制其生命周期/缓存以及根据配置更改行为。
为了方便[测试],我通常进行(至少)一种方法的两个版本:一个使用实例变量,一个仅使用传递给该方法的变量。
这听起来像是很多开销,但对我却没有太多好处。而是使您的实例变量具有
protected
或程序包可见性,然后在同一com.mycompany.whatever
程序包中找到单元测试。这样,您可以在测试期间随时检查和更改实例变量。#2 楼
首先,什么是依赖注入?简单。您有一个类,它有一个私有字段(设置为null),并声明一个公共设置方法,该方法提供该字段的值。换句话说,类(字段)的依赖项是由外部类(通过设置器)注入的。而已。
第二,Spring可以不使用XML(或很少使用)
如果您使用Spring 3.0.5.GA或更高版本,则可以使用JDK6 +的依赖注入支持。这意味着您可以使用
@Component
和@Resource
注释连接依赖项。为什么要完全使用Spring?
显然,依赖项注入可以简化单元测试。因为您所有的类都具有重要依赖项的设置器,并且可以使用您喜欢的模拟框架轻松地模拟这些设置器,以提供所需的行为。
除此之外,Spring还提供了许多模板,这些模板充当基类,使使用JEE标准技术变得轻而易举。例如,JdbcTemplate与JDBC配合良好,JpaTemplate与JPA兼容,JmsTemplate使JMS非常简单。 RestTemplate的简单性非常出色。例如:
RestTemplate restTemplate = new RestTemplate();
MyJaxbObject o = restTemplate.getForObject("https://secure.example.org/results/{param1}?param2={param2}",MyJaxbObject.class,"1","2");
,您就完成了。注入参数,您只需要为MyJaxbObject提供JAXB批注。如果您已经使用Maven JAXB插件从XSD自动生成了它们,那将完全没有时间。请注意,这里没有进行强制转换,也不需要声明编组器。一切都为您完成。
我可能永远都在谈论Spring的奇妙之处,但是也许最好的办法是尝试一个简单的代码尖峰,尝试连接RESTful Web服务以从注入的数据中抽取数据支持事务的DAO。
评论
是的RestTemplate非常棒。我有100行代码可以扔掉并替换为2-3行。
–凯文
2011年7月14日下午5:42
提倡:依赖注入还包括基于构造函数的方法。您不一定需要有setter。
– Darien
2011年7月15日在18:31
#3 楼
首先,您对依赖项注入的理解从根本上来说并不是错误的,但是与大多数人使用术语时的含义大不相同。您所描述的是实现可测试性的一种非常奇怪且非常规的方法。我建议您不要使用它,因为其他开发人员会对这种代码感到困惑。众所周知,依赖注入(并由Spring实现)意味着依赖关系是一个类具有实例化的对象(例如JDBC数据源)不是由类本身获取的,而是由容器“注入”的。因此,每个使用数据源的方法都没有两个版本;取而代之的是,您有一个依赖项注入配置,其中注入了“真实”数据源,而有一个注入了模拟。或者,如果注入是通过构造函数或getter进行的,则测试代码可以显式进行注入。
其次,Spring不仅是依赖项注入,尽管这是其核心功能。它还提供了声明式事务,作业计划,身份验证以及您可能需要的一系列其他功能(包括成熟的MVC Web框架)。还有其他框架提供相同的功能,但是除了Spring之外,只有Java EE才将它们全部集成。
评论
OP非常了解DI
–巴西
2015年6月15日在8:12
#4 楼
有关为什么要使用Spring的信息,请阅读本文(已存档)。总结:
J2EE应用程序往往包含过多的“管道”
代码。许多代码审查反复揭示出大部分不执行任何操作的
代码:JNDI查找代码,传输对象,
try / catch块以获取和释放JDBC资源。 。 。 。编写
并维护这样的管道代码证明了对资源的大量消耗
,应集中在应用程序的业务领域。
许多J2EE应用程序使用分布式对象模型。这是不适当的地方。这是过多代码和
代码重复的主要原因之一。在很多情况下,这在概念上也是错误的;与内部托管的应用程序相比,内部分布的应用程序要复杂得多,并且性能通常要差得多。当然,如果您的业务要求决定了分布式体系结构,则您需要
实现分布式体系结构,并接受由此产生的折衷(而Spring提供了在这种情况下可以提供帮助的功能) 。但是
没有令人信服的理由就不应该这样做。
EJB组件模型过于复杂。 EJB被认为是一种在J2EE应用程序中实现业务逻辑时降低复杂性的方法。在实践中它并没有成功。
EJB被过度使用。 EJB本质上是为内部
分布式事务性应用程序设计的。尽管几乎所有非平凡的应用程序都是事务性的,但分发不应构建在基本组件模型中。
许多“ J2EE设计模式”不是,实际上是设计模式,但是
技术限制的解决方法。过度使用分发以及使用诸如EJB之类的复杂API产生了许多可疑的设计模式。重要的是要仔细检查这些并仔细查看
J2EE应用程序很难进行单元测试。
J2EE应用程序很难进行单元测试。 J2EE API(尤其是EJB组件模型)是在敏捷运动开始之前定义的。因此,他们的设计没有考虑单元测试的便捷性。令人惊讶的是,通过API和隐式合同,很难在应用程序服务器之外测试基于EJB和许多其他J2EE API的应用程序。然而,在应用程序服务器外部进行单元测试对于实现高测试覆盖率和重现许多失败情况(例如与数据库的连接性丧失)来说是必不可少的。确保测试
在开发或维护过程中能够快速运行,
以最小化等待重新部署的非生产时间,这也至关重要。
某些J2EE技术具有简直失败了。这里的主要犯罪者是实体豆,事实证明,实体豆对生产力和对对象定向的约束没有造成灾难性的后果。
#5 楼
过去,我们仅使用核心Java,Servlet和JSP,html和xml,JDBC API编写了简单,高效,快速的应用程序和Web服务。足够好了; JUnit是一个很好的测试工具。Hibernate来简化SQL并实现数据库表与Java对象的真实映射,从而使层次结构关系反映在我们所谓的对象关系映射或ORM中。 。我爱它。特别是我们不必将ResultSet映射回Java对象或数据类型。
出现了Struts来将Model View Controller模式添加到我们的Web应用程序,这很好。
EJB带来了巨大的开销和痛苦,注释使代码看起来像鸡爪一样,现在Spring涌入了我们无辜的人们。
例如,我们现在将简单的jdbc url(用户)打包,首先传递到jdbc.properties,然后传递到休眠属性,然后传递到Spring bean!
相对于所有这些,考虑在真正需要的地方实现连接,就像在纯Java中所示的那样简单,这是我们在使用Spring进行所有热烈讨论之后真正要做的事情:
Connection connection = DriverManager.getConnection(url, user, pass);
这本身就是不言而喻的,它的大回合围绕着一圈又一圈地绕行,可以快速,轻松地完成一件简单的事情,而实际上并没有其他好处。就像将大量礼品纸包裹在一个很小的精美礼品上一样,这是您真正要保留的所有内容。
另一个示例是批量更新。在使用Spring之前,它涉及很多类和接口,在使用JdbcTemplate进行批处理更新之前,它是令人费解的。使用普通的jdbc,它的简单之处在于:
Statement statement = connection.createStatement();
statement.addBatch(sqlquery);
statement.executeBatch();
再简单不过了。
我不支持该框架。抱歉。到底谁在每次需要注射时都想要注射?
评论
该代码很简单,但是您的事务处理定义在哪里,以及如何对其进行测试?到春天,这两件事都变得更简单了。另外,您的Java代码直接绑定到db连接,除非您在外部存储连接URL和密码,否则spring也会使此操作变得更简单。
– NimChimpsky
2012年10月21日13:18
为此答案+1,请使用您自己的轻量级设计模式(GOF),用于连接池的单例,为数据库对象提供sql(字符串)和值(数组)的代理类(此方法为上述方法) ,取决于http方法),dbobject处理连接池,事务等,然后执行查询,然后释放。所有模块中只有一个对象使用,没有人需要过多的模板代码。奖励积分,在代理类和dbobject上设置单元测试。
–user2727195
15年7月2日在7:26
不过请查看Spring-Data-JPA!将pojo注释为实体,使用合理的名称(例如findHammerByWeight())实现接口并定义方法签名,并且spring为您实现方法,从而为您提供可注入的存储库,您可以在所有其他业务服务或控制器类中使用该存储库。
–mancini0
17年4月5日,下午2:14
#6 楼
Spring框架有什么作用?
Spring不仅是今天,被称为简单框架,它是一个完整的生态系统。
春季生态系统涵盖的主题:
Spring框架(例如,依赖注入,AOP ...)
Spring Cloud
Spring数据
Spring安全性
Spring Batch
Spring Social
请参阅此处,以全面了解生态系统。可以选择项目,以便您可以将Google Guice用于DI和例如Spring Security处理与安全性相关的事情。您不必购买整个生态系统。
Spring框架本身今天主要涵盖了
依赖注入
面向方面的编程,包括Spring的声明式事务管理
Spring MVC Web应用程序和RESTful Web服务框架
对JDBC,JPA,JMS的基础支持
spring.io的源代码
在通常,您可以说,Spring是代码中已实施的模式和实践的集合,可以帮助改善或加快您的应用程序开发周期。
最著名的是它(核心框架)在依赖注入领域的功能。 Spring本身具有所谓的控制容器反转或较短的IoC容器甚至更短的容器(有时将“ spring”用作同义词)。
什么是依赖项注入?
依赖关系注入意味着您的对象通过外部机制接收对其他对象的所有依赖关系。
说,您有一辆汽车,通常的实现方式是:
public class Car {
Engine e;
public Car() {
e = new Engine();
}
}
汽车对象取决于引擎。由于发动机是汽车的一员,因此不能将其换成例如发动机。测试引擎。
现在依赖注入开始起作用:
public class Car {
Engine e;
public Car(Engine e) {
this.e = e;
}
}
之后,您就可以切换引擎了。上面看到的称为构造函数注入。还有其他类型,例如setter-injection或method-injection。
Spring如何帮助您? Spring允许它使用注解
@Autowired
标记要注入的组件,并自动进行注入对象的布线-可能是,您要注入的组件本身具有依赖性。注射剂-可以说是通过@Component
public class Car {
Engine e;
@Autowired
public Car(Engine e) {
this.e = e;
}
}
标记的,但这只是Spring提供的众多功能之一。
我应该使用Spring吗?为什么或为什么不呢?
由于Spring不是很侵入性,它提供了许多您应该考虑使用spring的辅助工具。尤其对于新项目,Spring Boot非常有吸引力。 start.spring.io提供了易于使用的point'n'click界面来生成项目模板以进行入门。甚至可以使用
curl
来检索模板:curl start.spring.io
. ____ _ __ _ _
/\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Initializr :: https://start.spring.io
This service generates quickstart projects that can be easily customized.
Possible customizations include a project's dependencies, Java version, and
build system or build structure. See below for further details.
The services uses a HAL based hypermedia format to expose a set of resources
to interact with. If you access this root resource requesting application/json
as media type the response will contain the following links:
+-----------------+-----------------------------------------+
| Rel | Description |
+-----------------+-----------------------------------------+
| gradle-build | Generate a Gradle build file |
| gradle-project | Generate a Gradle based project archive |
| maven-build | Generate a Maven pom.xml |
| maven-project * | Generate a Maven based project archive |
+-----------------+-----------------------------------------+
...
另一方面,诸如spark或dropwizard之类的框架为快速创建Web应用程序提供了良好的起点。太。
评论
很有信息的答案!
– GOXR3PLUS
17年7月25日在7:23
同意,很好的答案。 OP,我同情您。我也有几个人向我展示Spring演示,他们在其中通过添加XML文件和2层间接访问来“简化”代码,以便他们可以在类上调用构造函数:)您确实只需要深入或进入真正好的演示,最终将弄清楚优点和缺点在哪里
–亚当·休斯(Adam Hughes)
17年8月18日在12:30
#7 楼
这是一个用Java编写的框架,其中包含许多使Web应用程序正常运行的功能(例如,对国际化的支持)。它还提供了一种将应用程序分层组织的好方法。使用它,从长远来看将为您节省大量时间。关于Spring的一本好书是:Expert Spring MVC和Web Flow
评论
我认为您确实需要一段时间尝试一下,以查看是否喜欢它以及它是否适合您的项目。我个人讨厌它。虽然可以使用XML或注释;请记住,Spring在配置思路上采取了惯例。这不一定是您必须处理的项目的清单。
虽然这个问题的确很广泛,但我认为应该保持开放。我将其读为“ Spring对中型项目有什么好处?”,这是一个很好的问题。
我强烈建议您阅读我最喜欢的技术书:Craig Walls撰写的Spring in Action,第三版。这是一本很好的读物,它将改变您的编程方式。
考虑到Enterprise Java,更容易回答Spring不做的事情...