【问题标题】:What exactly is Spring Framework for? [closed]Spring 框架到底是干什么用的? [关闭]
【发布时间】:2010-11-06 21:32:45
【问题描述】:

我听到很多关于Spring 的消息,人们在整个网络上都在说 Spring 是一个很好的 Web 开发框架。简而言之,Spring Framework 到底是什么?我为什么要在纯 Java 上使用它。

【问题讨论】:

  • 我知道这个问题非常广泛,但我确实认为在这个非常具体的情况下,这个问题对于经常被认为 Spring 足够流行的人谈论 Spring 的联合开发人员来说非常重要甚至没有必要告诉它做什么。毕竟,如果您从未听说过 Instagram 及其用途,请举手……(坦白:我从未使用过 Insta)
  • 这个问题是10年前问的,那时候Spring比现在小一点,所有子项目都有,比如Spring Boot、Spring Data、Spring Rest等。其实这就是为什么由于这个问题的广泛性,一年前更接近。当我问这个问题时,我只是想了解 DI 以及为什么需要它。

标签: java spring frameworks


【解决方案1】:

基本上 Spring 是 的框架,这是一种允许构建非常解耦的系统的模式。

问题

例如,假设您需要列出系统的用户并因此声明一个名为UserLister的接口:

public interface UserLister {
    List<User> getUsers();
}

也许还有一个访问数据库以获取所有用户的实现:

public class UserListerDB implements UserLister {
    public List<User> getUsers() {
        // DB access code here
    }
}

在您看来,您需要访问一个实例(只是一个示例,请记住):

public class SomeView {
    private UserLister userLister;

    public void render() {
        List<User> users = userLister.getUsers();
        view.render(users);
    }
}

请注意,上面的代码没有初始化变量userLister。我们应该做什么?如果我像这样显式实例化对象:

UserLister userLister = new UserListerDB();

...我将视图与访问数据库的类的实现结合起来。如果我想从数据库实现切换到另一个从逗号分隔文件中获取用户列表的实现(记住,这是一个示例),该怎么办?在这种情况下,我会再次转到我的代码并将上面的行更改为:

UserLister userLister = new UserListerCommaSeparatedFile();

这样的小程序没有问题,但是......在一个有数百个视图和类似数量的业务类的程序中会发生什么?维护成为一场噩梦!

Spring(依赖注入)方法

Spring 所做的是通过使用 XML 文件或注释将类连接,这样所有对象都由 Spring 实例化和初始化,并在右侧 injected位置(Servlet、Web 框架、业务类、DAO 等,等等……)。

回到 Spring 中的示例,我们只需要为 userLister 字段设置一个设置器,并拥有一个像这样的 XML 文件:

<bean id="userLister" class="UserListerDB" />

<bean class="SomeView">
    <property name="userLister" ref="userLister" />
</bean>

或者更简单地用@Inject注释我们视图类中的文件:

@Inject
private UserLister userLister;

这样,当视图被创建时神奇地就会有一个UserLister准备好工作。

List<User> users = userLister.getUsers();  // This will actually work
                                           // without adding any line of code

太棒了!不是吗?

  • 如果你想使用 UserLister 接口的另一个实现怎么办?只需更改 XML。
  • 如果没有准备好 UserLister 实现怎么办? 编写 UserLister 的临时模拟实现并简化视图的开发。
  • 如果我不想再使用 Spring 怎么办? 不要使用它!您的应用程序没有耦合到它。 Inversion of Control 声明:“应用程序控制框架,而不是框架控制应用程序”。

还有一些其他的依赖注入选项,在我看来,除了简单、优雅和稳定之外,Spring 如此出名的原因是 SpringSource 的人编写了许多 POJO,有助于将 Spring 与许多其他常见的集成框架,而不会侵入您的应用程序。此外,Spring 有几个不错的子项目,如 Spring MVC、Spring WebFlow、Spring Security 以及一大堆等等。

希望这会有所帮助。无论如何,我鼓励您阅读 Martin Fowler's article 关于依赖注入和控制反转的内容,因为他比我做得更好。 了解基础知识后看看Spring Documentation,在我看来,它 曾经是有史以来最好的Spring书籍。 p>

【讨论】:

  • 必须更改一行代码和一行 XML 有什么区别?工作量和维护地狱完全一样,甚至更糟,因为外部 xml 文件可能会增加复杂性?对不起,但我只是不明白,我根本看不到任何好处。如果我遗漏了什么,请填写我。
  • @fred - 想象一下你正在做单元测试。如果没有依赖注入(DI 可以与注解或​​ XML 一起使用),您将无法正确测试,因为您无法模拟依赖项。
  • @fred - 在 XML 中定义所有注入确实没有什么意义。这是一个巨大的维护开销。因此,EJB 引入了注解注入点的概念。这些要简单得多,并且将注入一个默认实例(对于单元测试,这可以更改一次)。这非常有效,以至于 Spring 现在已经复制了这种方法。请注意,如果需要(但仅在确实需要时)注释仍然可以被 EJB 中的 XML 覆盖。
  • 或者,你知道,使用工厂静态方法。更改工厂的返回类型,现在所有使用该返回值的类都更改了。 Presto 现在不再需要 Spring...
  • @mmcrae 我宁愿在我的 IDE 中进行一次重构调用,也不愿编写 XML。
【解决方案2】:

Spring包含正如 Skaffman 正确指出的)一个 MVC 框架。简而言之,这里是我的输入。 Spring 支持服务层、Web 层和业务层的分离,但它真正最擅长的是对象的“注入”。因此,为了解释这一点,请考虑以下示例:

public interface FourWheel
{
   public void drive();
}

public class Sedan implements FourWheel
{
   public void drive()
   {
      //drive gracefully
   }
}

public class SUV implements FourWheel
{
   public void drive()
   {
      //Rule the rough terrain
   }
}

现在您的代码中有一个名为 RoadTrip 的类,如下所示

public class RoadTrip
{
    private FourWheel myCarForTrip;
}

现在只要你想要一个 Trip 的实例;有时您可能需要 SUV 来初始化 FourWheel,或者有时您可能需要 Sedan。根据具体情况,这真的取决于你想要什么。

要解决此问题,您需要将工厂模式作为创建模式。工厂返回正确实例的地方。所以最终你会得到很多胶水代码,只是为了正确地实例化对象。如果没有胶水代码,Spring 可以最好地完成胶水代码的工作。您在 XML 中声明映射,它会自动初始化对象。它还对实例使用单例架构做了大量工作,这有助于优化内存使用。

这也称为控制反转。执行此操作的其他框架有 Google guice、Pico 容器等。

除此之外,Spring 还具有验证框架,广泛支持与 JDBC、iBatis 和 Hibernate(以及更多)协作的 DAO 层。提供对数据库事务的出色事务控制。

关于 Spring 的更多内容可以在“Pro Spring”等好书中读到。

以下网址可能也会有所帮助。
http://static.springframework.org/docs/Spring-MVC-step-by-step/
http://en.wikipedia.org/wiki/Spring_Framework
http://www.theserverside.com/tt/articles/article.tss?l=SpringFramework

【讨论】:

  • Spring 包含一个 MVC 框架。但它远不止于此。
  • 不想吹毛求疵,WebMVC 是核心 spring 发行版的一部分。 Webflow、RCP 等都不是。
  • 很好,我不知道你可以在 Java 中实例化接口类型的对象 - 这是非法的 @skaffman 帮助我理解这个答案(参见 FourWheel 实例)
【解决方案3】:

过去,Spring 只是一个依赖注入框架,就像 (Guice, PicoContainer,...),但现在它是构建您的企业应用程序的整体解决方案。

spring 依赖注入,当然,spring 的核心仍然存在(您可以在此处查看其他好的答案),但还有更多来自 spring...

Spring 现在有很多项目,每个项目都有一些子项目 (http://spring.io/projects)。当有人说起spring,你一定要搞清楚他说的是什么spring project,是只有spring core,也就是所谓的spring framework,还是另一个spring项目。

一些值得一提的春季项目是:

如果您的应用程序需要更多指定功能,您也可以在那里找到:

  • Spring Batch 旨在支持
    开发的批处理框架 批量申请
  • Spring HATEOAS 基于 HATEOAS 主体轻松创建 REST API
  • Spring MobileSpring Andriod 用于移动应用程序开发
  • Spring Shell 构建功能齐全的 shell(又称命令行)应用程序
  • Spring CloudSpring Cloud Data Flow 用于云应用程序

那里还有一些小项目,例如 spring-social-facebook (http://projects.spring.io/spring-social-facebook/)

您可以将 spring 用于 Web 开发,因为它具有 Spring MVC 模块,该模块是 Spring Framework 项目的一部分。或者您可以将 spring 与另一个 Web 框架一起使用,例如 struts2

【讨论】:

  • 其实我很想看到 Spring 的 mvc、data、jpa 等部分可以选择不使用 Spring 的核心 DI,而是把 Dagger 放在 Spring 的核心。
【解决方案4】:

春天有什么用?我将很快回答这个问题,但首先,让我们再看一下 victor hugo 的示例。这不是一个很好的例子,因为它不能证明需要一个新框架。

public class BaseView {
  protected UserLister userLister;

  public BaseView() {
    userLister = new UserListerDB(); // only line of code that needs changing
  }
}

public class SomeView extends BaseView {
  public SomeView() {
    super();
  }

  public void render() {
    List<User> users = userLister.getUsers();
    view.render(users);
  }
}

完成!所以现在即使你有成百上千的视图,你仍然只需要改变一行代码,就像在 Spring XML 方法中一样。 但是更改一行代码仍然需要重新编译而不是您说的编辑 XML?好吧,我挑剔的朋友,使用 Ant 和脚本吧!

那么春天有什么用呢?这是为了:

  1. 盲目跟风的开发者
  2. 雇主不想雇用研究生程序员,因为他们在 Uni 不教授此类框架
  3. 以糟糕的设计开始并需要拼凑的项目(如 victor hugo 的示例所示)

延伸阅读:http://discuss.joelonsoftware.com/?joel.3.219431.12

【讨论】:

  • 除了沮丧之外,我想知道你的论点。我不知道任何不能用来产生糟糕设计的编程工具。你的目标是使用框架你可以让糟糕的代码做很多事情。这是普遍正确的,而不是特定于 Spring 的。否则有什么意义?你不认为有能力的开发人员可以充分利用 Spring 提供的东西——特别是他们使用框架的哪些工具吗?至少我很确定您并不暗示没有 Spring 开发人员听说过扩展类。不过,进一步阅读很有趣。
  • 此外,您的示例有效,因为视图只需要一个注入服务 (UserLister),但如果它需要多个服务,不共享​​>在不同的 BaseView 之间的孩子? (幸运的是)Java 中没有多重继承。
  • @EdouardBerthe 公平点。我的回答不是试图忽视 DI,它只是指出接受的答案中显示的例子不是最好的;您提出的方案很可能会更好。我真正想说的不是你不需要 DI,而是你不需要一个完整的框架来完成它。
【解决方案5】:

非常简短的总结,我会说 Spring 是您应用程序中的“粘合剂”。它用于集成不同的框架和您自己的代码。

【讨论】:

    【解决方案6】:

    春天是三样东西。

    1. Spring 处理依赖注入,我建议您阅读 Martin Fowler 关于依赖注入的精彩介绍。
    2. Spring 所做的第二件事是以一种非常优雅的方式包装优秀的 Java 库,以便在您的应用程序中使用。一个很好的例子请看 Spring 如何包装 Task Executors 和 Quartz Scheduler。
    3. 第三,Spring 提供了一系列 Web 内容的实现,例如 REST、MVC Web 框架等。他们认为,由于您在前两个中使用 Spring,也许您可​​以将它用于您的 Web 应用程序所需的一切。

    问题在于 Spring DI 是经过深思熟虑的,围绕其他事物的包装器也经过深思熟虑,因为其他事物都考虑了一切,而 Spring 很好地封装了它。 MVC 和 REST 的 Spring 实现以及所有其他东西都做得不太好(YMMV,恕我直言),但也有例外(Spring Security 是炸弹)。 所以我倾向于将 Spring 用于 DI,以及它很酷的包装器,但更喜欢用于 Web(我非常喜欢 Tapestry)、REST(Jersey 非常健壮)等的其他东西。

    【讨论】:

    • YMMV,恕我直言 - 您的里程可能会有所不同,对于像我这样不流利缩写的人来说,我的拙见...
    【解决方案7】:

    您可能希望在 Spring 的 Web 应用程序中得到什么 -

    • Spring MVC,2.5+ 允许您将 POJO 用作控制器类,这意味着您不必从任何特定框架扩展(如在 Struts 或 Spring 2.5 之前的版本中)。由于依赖注入,控制器类的测试也非常简单
    • Spring 与 Hibernate 的集成,很好地简化了该 ORM 解决方案的工作(在大多数情况下)
    • 将 Spring 用于 Web 应用程序使您能够在应用程序的所有级别使用域对象 - 使用 Hibernate 映射的相同类是您用作“表单 bean”的类。从本质上讲,这将导致更强大的域模型,部分原因是它将减少类的数量。
    • Spring 表单标签使创建表单变得更加容易,没有太多麻烦。

    此外,Spring 非常庞大——因此您可能会对在 Web 应用程序中使用许多其他东西感兴趣,例如 Spring AOP 或 Spring Security。但是上面列出的四件事描述了 Web 应用程序中使用的 Spring 的常见组件。

    【讨论】:

      【解决方案8】:

      我看到了两个部分:

      1. “Spring 到底是干什么用的”-> 查看 victor hugo 接受的答案。
      2. “[...] Spring 是 [a] 很好的 Web 开发框架”-> 说这句话的人是在谈论 Spring MVC。 Spring MVC 是 Spring 的众多部分之一,它是一个利用 Spring 的一般特性(如依赖注入)的 Web 框架。这是一个非常通用的框架,因为它非常可配置:您可以使用不同的数据库层(Hibernate、iBatis、普通 JDBC)、不同的视图层(JSP、Velocity、Freemarker...)

      请注意,您可以在 Web 应用程序中很好地使用 Spring,而无需使用 Spring MVC。我想说大多数 Java Web 应用程序都是这样做的,同时使用其他 Web 框架,如 Wicket、Struts、Seam ......

      【讨论】:

        【解决方案9】:

        Spring 非常适合将类的实例粘合在一起。你知道你的 Hibernate 类总是需要一个数据源,Spring 将它们连接在一起(并且也有一个数据源的实现)。

        您的数据访问对象将始终需要 Hibernate 访问,Spring 为您将 Hibernate 类连接到您的 DAO。

        此外,Spring 基本上为您提供了一堆库的可靠配置,并在其中指导您应该使用哪些库。

        Spring 确实是一个很棒的工具。 (我说的不是 Spring MVC,只是基础框架)。

        【讨论】:

          【解决方案10】:

          优势是Dependency Injection (DI)。这意味着将创建对象的任务外包。让我用一个例子来解释。

          public interface Lunch
          {
             public void eat();
          }
          
          public class Buffet implements Lunch
          {
             public void eat()
             {
                // Eat as much as you can 
             }
          }
          
          public class Plated implements Lunch
          {
             public void eat()
             {
                // Eat a limited portion
             }
          }
          

          现在在我的代码中,我有一个如下所示的午餐决定类:

          public class LunchDecide {
              private Lunch todaysLunch;
              public LunchDecide(){
                  this.todaysLunch = new Buffet(); // choose Buffet -> eat as much as you want
                  //this.todaysLunch = new Plated(); // choose Plated -> eat a limited portion 
              }
          }
          

          在上面的类中,根据我们的心情,我们选择 Buffet() 或 Plated()。然而,这个系统是紧密耦合的。每次我们需要不同类型的对象时,我们都需要更改代码。在这种情况下,注释掉一行!想象一下,有 50 个不同的人使用 50 个不同的类。这将是一团糟。在这种情况下,我们需要对系统进行解耦。让我们重写LunchDecide 类。

          public class LunchDecide {
              private Lunch todaysLunch;
              public LunchDecide(Lunch todaysLunch){
                  this.todaysLunch = todaysLunch
                  }
              }
          

          请注意,我们没有使用 new 关键字创建对象,而是将午餐类型对象的引用作为参数传递给构造函数。在这里,对象创建是外包的。可以使用 Xml 配置文件(旧版)或 Java 注释(现代版)连接此代码。无论哪种方式,将在运行时决定创建哪种类型的对象。 Xml 将一个对象注入到我们的代码中——我们的代码依赖于 Xml 来完成这项工作。因此,依赖注入(DI)。 DI 不仅有助于使我们的系统松散耦合,它还简化了单元测试的编写,因为它允许模拟依赖项。最后但并非最不重要的一点是,DI 简化了面向方面的编程 (AOP),这导致了进一步的解耦和模块化的增加。 另请注意,上面的 DI 是构造函数注入。 DI 也可以通过 Setter Injection 完成 - 与封装相同的普通旧 setter 方法。

          【讨论】:

          • 但即使在 Spring 的情况下,我们仍然会定义 bean。并且 bean id 将在代码中给出,不是吗?所以如果你明天换bean,你还是得改代码,不是吗?那么有什么好处呢。
          • @ArpanBuch 我认为 spring 的好处是您可以选择不同的实现而无需重新编译任何代码(只要其他实现已经存在)。我是初学者,所以我可能是错的。
          【解决方案11】:

          接受的答案不涉及注释的使用,因为 Spring 引入了对配置的各种注释的支持。

          Spring注解方式(依赖注入)

          还有另一种使用 XML 文件将类连接起来的方法:注释。让我们使用接受的答案中的示例,并使用注释@Component@Service@Repository@Configuration 之一直接在类上注册 bean:

          @Component
          public class UserListerDB implements UserLister {
              public List<User> getUsers() {
                  // DB access code here
              }
          }
          

          这样,当创建视图时,它就会神奇地拥有一个准备工作的 UserLister。

          上面的语句是有效的,不需要任何 XML 文件的使用和与另一个注释 @Autowired 的连接,它找到了相关的实现并将其注入。

          @Autowired
          private UserLister userLister;
          

          在用于使 bean 实现注入的方法上使用 @Bean 注释。

          【讨论】:

          • 错了。您不能在类级别上使用 @Bean 注释。必须是@Component@Service@Repository 等之一。休息是正确的。您也许还应该指出,以这种方式自动装配接口仅在类路径中只有 1 个适合注入的候选类时才有效,否则 Spring 应用程序错误。
          • @StefanoL:是的,你是对的。我不知道人们忽略了我的错误。感谢您的评论。
          【解决方案12】:
          • 与 J2EE 相比,Spring 是一个轻量且灵活的框架。
          • Spring 容器充当控制反转。
          • Spring 使用 AOP,即代理和单例、工厂和模板方法设计模式。
          • 分层架构:关注点分离和可重用层以及易于维护。

          【讨论】:

          • Spring Framework help you with several things like, don't reinvent the wheel. you can connect very easily with some database just using Spring Data, or create schedule tasks like CronJob or Windows Task. amazing !
          【解决方案13】:

          Spring 是Enterprise JavaBeans (EJB) 技术的一个很好的替代品。它还具有 Web 框架和 Web 服务框架组件。

          【讨论】:

          • 我可以更正吗? 替代(可怕的)EJB 2 ... 似乎“新 EJB”(部分是 JPA 2 等)已被广泛接受。春季部分“一种 EJB”的“欢乐时光”似乎已经过去。广告。 2015
          【解决方案14】:

          Spring 最初是一个相当简单的依赖注入系统。现在它很大,里面什么都有(除了众所周知的厨房水槽)。

          但不要害怕,它是非常模块化的,所以你可以只使用你想要的部分。

          要查看一切从哪里开始尝试:

          http://www.amazon.com/Expert-One-Design-Development-Programmer/dp/0764543857/ref=sr_1_1?ie=UTF8&s=books&qid=1246374863&sr=1-1

          它可能很旧,但它是一本很棒的书。

          关于这次专门介绍 Spring 的另一本好书,请参阅:

          http://www.amazon.com/Professional-Java-Development-Spring-Framework/dp/0764574833/ref=sr_1_2?ie=UTF8&s=books&qid=1246374863&sr=1-2

          它还引用了旧版本的 Spring,但绝对值得一看。

          【讨论】:

            【解决方案15】:

            Spring 一开始是依赖注入,然后为几乎所有东西添加了封装之王(JPA 实现的封装等)。

            长篇大论... Spring 的大多数部分都提供 XML 解决方案(XML 脚本引擎 ... brrrr),所以对于 DI,我使用 Guice

            很好的库,但是随着depnedenciec的增长,例如Spring JDBC(可能是一个带有实名参数的Java jdbc解决方案)接下来取自maven 4-5。

            使用 Spring MVC(“大弹簧”的一部分)进行 Web 开发......它是“基于请求”的框架,有圣战“请求与组件”......取决于你

            【讨论】:

            • 我相信现在 Spring 框架正试图从 XML 转移到 Annotations 和 Java 配置。
            【解决方案16】:

            过去我从纯技术角度考虑 Spring 框架。

            鉴于团队合作和开发企业 Web 应用程序的一些经验 - 我会说 Spring 通过 解耦 其各个元素(bean)更快地开发应用程序(Web 应用程序) )。更快的发展使它如此受欢迎。 Spring 允许将构建(连接)应用程序的责任转移到 Spring 框架上。 Spring 框架的依赖注入负责将各个 bean 连接/连接到工作应用程序中。

            这样,一旦定义了 bean 之间的接口,开发人员就可以更加专注于单个组件(bean)的开发。

            此类应用程序的测试很容易 - 主要关注单个 bean。它们可以轻松解耦和模拟,因此单元测试快速高效。

            Spring 框架定义了多个专门的 bean,例如 @Controller (@Restcontroller)、@Repository@Component 服务于网络目的。 Spring 与 Maven 一起为开发人员提供了一种直观的结构。 团队合作既简单又快速,因为各个元素分开并可以重复使用。

            【讨论】:

              【解决方案17】:

              Spring 框架对于 Web 开发来说绝对是不错的,并且更具体地适用于 restful api 服务。

              因为它的dependency injection 和与其他模块的集成,如spring securityspring aopmvc frameworkmicroservices

              在任何应用程序中,安全性很可能是一项要求。
              如果您的目标是构建需要长期维护的产品,那么您将需要利用 Aop 概念。

              如果您的应用程序需要大量流量从而增加负载,则需要使用微服务概念。

              Spring 在一个平台上提供了所有这些功能。支持many modules
              最重要的是,spring 是open source 和一个可扩展的框架,到处都有一个钩子,可以在生命周期中集成自定义代码。

              Spring Data 是一个提供与您的项目集成的项目。


              所以 spring 几乎可以满足所有需求。

              【讨论】:

                猜你喜欢
                • 2021-08-29
                • 1970-01-01
                • 2011-06-20
                • 2016-10-31
                • 2023-03-07
                • 1970-01-01
                • 2018-07-27
                • 2016-12-29
                • 1970-01-01
                相关资源
                最近更新 更多