Spring Framework究竟是什么?

Mak*_*sim 607 java spring frameworks web-applications web

我听到很多关于Spring的消息,人们在网上都说Spring是一个很好的Web开发框架.Spring Framework究竟是什么?

vic*_*ugo 702

基本上Spring是的框架,它是一种允许构建非常分离的系统的模式.

问题

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

public interface UserLister {
    List<User> getUsers();
}
Run Code Online (Sandbox Code Playgroud)

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

public class UserListerDB implements UserLister {
    public List<User> getUsers() {
        // DB access code here
    }
}
Run Code Online (Sandbox Code Playgroud)

在您的视图中,您将需要访问一个实例(只是一个示例,请记住):

public class SomeView {
    private UserLister userLister;

    public void render() {
        List<User> users = userLister.getUsers();
        view.render(users);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

UserLister userLister = new UserListerDB();
Run Code Online (Sandbox Code Playgroud)

...我将视图与访问数据库的类的实现结合起来.如果我想从数据库实现切换到另一个从逗号分隔文件中获取用户列表的内容(请记住,这是一个例子),该怎么办?在那种情况下,我会再次访问我的代码,并通过以下方式更改最后一行:

UserLister userLister = new UserListerCommaSeparatedFile();
Run Code Online (Sandbox Code Playgroud)

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

Spring(依赖注入)方法

什么春天确实是来连线通过使用XML文件或注解,这样所有的对象实例化和春天初始化和班达注射在适当的地方(Servlet的Web框架,业务类,DAO的,等,等,等...).

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

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

<bean class="SomeView">
    <property name="userLister" ref="userLister" />
</bean>
Run Code Online (Sandbox Code Playgroud)

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

@Inject
private UserLister userLister;
Run Code Online (Sandbox Code Playgroud)

当视图被创建这样奇迹般地将有一个UserLister准备工作.

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

太棒了!不是吗?

  • 如果您想使用UserLister界面的其他实现,该怎么办?只需更改XML即可
  • 如果没有UserLister准备就绪怎么办?编写一个时间模拟实现UserLister并简化视图的开发
  • 如果我不想再使用Spring怎么办?只是不要使用它!您的应用程序未与其耦合.控制反转状态:"应用程序控制框架,而不是框架控制应用程序".

在那里有一些其他的依赖注入选项,我认为Spring除了简单,优雅和稳定之外如此着名是SpringSource的人已经编写了许多POJO,它们有助于将Spring与许多其他常见框架集成,而不是侵入你的应用程序.Spring还有几个很好的子项目,比如Spring MVC,Spring WebFlow,Spring Security,还有一些loooong的etceteras列表.

希望这可以帮助.无论如何,我鼓励你阅读Martin Fowler关于依赖注入和控制反转的文章,因为他做得比我好.了解基础知识去看一下后Spring文档,在我看来,这 曾经是最好的春季书永远.

  • 不得不改变一行代码和一行XML之间的区别?努力和维护是完全相同的,甚至更糟,因为外部xml文件可能会增加复杂性?对不起,我只是没有得到它,我没有看到任何好处.如果我错过了什么,请填写我. (141认同)
  • 或者,您知道,使用工厂静态方法.更改工厂的返回类型,现在所有使用该返回值的类都会更改.*Presto*现在不再需要Spring了...... (34认同)
  • @fred - 想象一下你正在进行单元测试.没有依赖注入(DI可以与注释或XML一起使用),您无法正确测试,因为您无法模拟依赖项. (22认同)
  • @fred - 用XML定义所有注入确实没什么意义.维护是一个巨大的开销.因此,EJB引入了注入点注释的概念.这些更简单,并且将注入默认实例(对于单元测试,这可以更改一次).这非常有效,Spring现在已经复制了这种方法.请注意,如果需要(但仅在确实需要时)注释仍可由EJB中的XML覆盖. (17认同)
  • @mmcrae我宁愿在我的IDE中进行一次重构调用而不是编写XML. (15认同)
  • @fred此外,在现实世界中,它将改变一行XML与一堆代码行. (8认同)
  • @fred在这个例子中,我们看到`UserLister`对象只被使用一次.所以是的,在这里,它是"在XML中更改一行,或在代码中更改一行"的选择.但是现在,想象一下,在一个更大的应用程序中,"UserLister"被用在多个类/包中.现在显而易见的是,您宁愿更改XML中的一行而不是查找类的每次使用并更改实例化(可能是十几个类) (7认同)
  • 对于那些不想花费精力学习,思考和使用api的人来说,春天是有益的......它绝对没有任何东西,只能解决很少的问题.增加了必须加载无用弹簧类的音调和潜在的内存泄漏的复杂性以及学习理解框架是一种憎恶.除了只是说"我知道如何编写xml配置,嘻嘻"之后我认为没有用处.不管怎样,75票不能错...春天或多或少是无用的库,人们使用它的唯一原因是因为它是流行.使用java近10年我还没有看到有用的实现 (4认同)
  • @mmcrae为什么要更改许多行代码?该类实例化依赖项,因此您只需为要在XML中替换的每个"不同"行替换一行代码.我不支持Spring,也不支持它. (3认同)
  • &gt; 如果我不想再使用 Spring 怎么办?只是不要使用它!您的应用程序未与其耦合。啊,是的,所有这些“@Autowired”/“@Inject”字段仍然可以工作,无需 Spring 为我设置值 (2认同)

Pri*_*ank 62

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
   }
}
Run Code Online (Sandbox Code Playgroud)

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

public class RoadTrip
{
    private FourWheel myCarForTrip;
}
Run Code Online (Sandbox Code Playgroud)

现在每当你想要一个Trip的实例; 有时你可能想要一辆SUV来初始化FourWheel,或者有时你可能想要Sedan.这取决于你想要的具体情况.

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

这也称为控制反转.其他框架是谷歌guice,Pico容器等.

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

春天还有很多东西可以在像"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框架.但它是很多,不止于此. (5认同)

Ali*_*ahi 45

过去,Spring只是一个依赖注入框架工作(Guice,PicoContainer,...),但现在有一天它是构建企业应用程序的完整解决方案.

春天依赖注入,当然是春天的核心仍然存在(你可以在这里查看其他好的答案),但春天​​还有更多......

Spring现在有很多项目,每个项目都有一些子项目(http://spring.io/projects).当有人谈到春天时,你必须找出他正在谈论的春季项目,它只是弹簧核心,它被称为弹簧框架,或者它是另一个弹簧项目.

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

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

  • Spring Batch 批处理框架旨在实现
    批处理应用程序的开发
  • Spring HATEOAS基于HATEOAS主体轻松创建REST api
  • Spring MobileSpring Andriod用于移动应用程序开发
  • Spring Shell 构建了一个功能齐全的shell(也就是命令行)应用程序
  • 适用于云应用程序的Spring CloudSpring Cloud数据流

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

您可以使用spring进行Web开发,因为它具有作为Spring Framework项目Spring MVC一部分的模块.或者你可以使用spring和另一个web框架工作,比如struts2.


Ash*_*Ash 23

什么是春天?我将很快回答这个问题,但首先,让我们再看一下维克多·胡戈的例子.这不是一个很好的例子,因为它不能证明需要一个新的框架.

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

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

那春天是什么?这是为了:

  1. 跟随牛群的盲人开发者
  2. 雇主谁不想雇用研究生程序员,因为他们没有在Uni教授这样的框架
  3. 从糟糕的设计开始并需要拼凑而成的项目(如victor hugo所示)

进一步阅读:http://discuss.joelonsoftware.com/?joel.3.219431.12

  • 撇开沮丧,我想知道你的论点.我不知道任何你不能用来制作糟糕设计的编程工具.你的目标是使用框架,你可以做坏代码做很多事情.这是普遍真实的,而不是Spring特有的.否则有什么意义呢?您是否认为有能力的开发人员可以充分利用Spring提供的功能 - 特别是他们使用的框架工具?至少我很确定你并不是说没有Spring开发人员听说过扩展类.然而,进一步的阅读是热闹的. (11认同)
  • 此外,您的示例有效,因为视图只需要一个注入服务(`UserLister`),但如果它需要多个服务,*不共享*不同的`BaseView`的子项之间怎么办?(幸运的是)Java中没有多重继承. (2认同)

Joh*_*han 18

非常简短的总结,我会说Spring是你应用程序中的"胶水".它用于集成不同的框架和您自己的代码.


小智 14

春天是三件事.

  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 for DI,它的酷包装但更喜欢Web的其他东西(我喜欢Tapestry),REST(Jersey非常健壮)等等.

  • YMMV,恕我直言 - 你的里程可能会有所改变,我谦卑的意见对那些不像我这样不懂流言的人来说...... (9认同)

bpa*_*apa 11

在Spring的Web应用程序中你可能想要的东西 -

  • Spring MVC,2.5+允许您使用POJO作为Controller类,这意味着您不必从任何特定框架扩展(如Struts或Spring pre-2.5).控制器类也很容易测试,部分归功于依赖注入
  • Spring与Hibernate集成,可以很好地简化ORM解决方案的工作(大多数情况下)
  • 将Spring用于Web应用程序使您可以在应用程序的所有级别使用域对象 - 使用Hibernate映射的相同类是您用作"表单bean"的类.从本质上讲,这将导致更强大的领域模型,部分原因在于它将减少类的数量.
  • Spring表单标签可以更轻松地创建表单而不会有太多麻烦.

另外,Spring很大 - 所以你可能有兴趣在Spring AOP或Spring Security等Web应用程序中使用很多其他东西.但是上面列出的四件事描述了在Web应用程序中使用的Spring的常见组件.


Tom*_*Leu 9

我看到两个部分:

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

请注意,您可以在不使用Spring MVC的情况下在Web应用程序中很好地使用Spring.我想说大多数Java Web应用程序都会这样做,同时使用其他Web框架,如Wicket,Struts,Seam,......


ste*_*own 8

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

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

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

Spring真的是一个很棒的工具.(我不是在谈论Spring MVC,只是基础框架).


Sum*_*rel 6

优点是依赖注入(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
   }
}
Run Code Online (Sandbox Code Playgroud)

现在在我的代码中,我有一个 LunchDecide 类,如下所示:

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 
    }
}
Run Code Online (Sandbox Code Playgroud)

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

public class LunchDecide {
    private Lunch todaysLunch;
    public LunchDecide(Lunch todaysLunch){
        this.todaysLunch = todaysLunch
        }
    }
Run Code Online (Sandbox Code Playgroud)

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


Nik*_*las 5

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

Spring(依赖注入)方法

还有另一种方法可以使用XML文件连接类:注释.让我们用从接受答案的例子,并直接使用注释的一个类注册豆@Component,@Service,@Repository@Configuration:

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

这样,当创建视图时,它会神奇地使UserLister准备好工作.

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

@Autowired
private UserLister userLister;
Run Code Online (Sandbox Code Playgroud)

使用@Bean注释上用来获取bean的实现注入的方法.