Spring MVC是Spring框架中用于Web应用开发的一个模块。Spring MVC的MVC是Model-View-Controller的缩写。它是一个广泛应用于图像化用户交互开发中的设计模式,不仅常见于Web开发,也广泛应用于如Swing和JavaFX等桌面开发。

Spring MVC基于Spring框架、Servlet和JSP(JavaServer Page),在掌握这3门技术的基础上学习Spring MVC将非常容易。

Spring框架是一个开源的企业应用开发框架,作为一个轻量级的解决方案,它包含20多个不同的解决方法。我们主要关注Core、Spring Bean、Spring MVC和Spring MVC Test模块。

一 下载Spring

1、Spring下载

Spring框架下载官网:http://spring.io/projects,具体可以参考博客Spring框架下载方法

也可以直接下载:URL为最Spring最新5.1.6版本地址,获取其他版本只需修改下面链接的5.1.6的版本号信息成想要的版本即可:https://repo.spring.io/webapp/#/artifacts/browse/tree/General/libs-release-local/org/springframework/spring/5.1.6.RELEASE

将下载好的zip解压到任意目录,在解压的目录中,包含相应的文档和Java源代码,其中libs文件下为基于Spring框架开发应用所需要的jar文件。

Spring MVC -- Spring框架入门(IoC、DI以及XML配置文件)

2、Spring依赖包下载

关于spring的spring-framework-3.0.2.RELEASE-dependencies.zip包的下载:http://s3.amazonaws.com/dist.springframework.org/release/SPR/spring-framework-3.0.2.RELEASE-dependencies.zip

3、下载Spring源码

Spring框架是一个开源项目,如果你想要尚未发布的最新版本的Spring,可以使用在github上下载源代码:https://github.com/spring-projects/spring-framework

二 IoC和DI

Spring框架有两个重要的概念:控制翻转、依赖注入。 

1、IoC是什么

Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:

  • 谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等);
  • 为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

用图例说明一下,传统程序设计如图,都是主动去创建相关对象然后再组合起来:

Spring MVC -- Spring框架入门(IoC、DI以及XML配置文件)

当有了IoC/DI的容器后,在客户端类中不再主动去创建这些对象了:

Spring MVC -- Spring框架入门(IoC、DI以及XML配置文件)

2  IoC能做什么

IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。

其实IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。

IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。

3、IoC和DI

DI—Dependency Injection,即“依赖注入”:是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:

  • 谁依赖于谁:当然是应用程序依赖于IoC容器;
  • 为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;
  • 谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;
  • 注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。

IoC和DI由什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。

注:如果想要更加深入的了解IoC和DI,请参考大师级人物Martin Fowler的一篇经典文章《Inversion of Control Containers and the Dependency Injection pattern》,原文地址:http://www.martinfowler.com/articles/injection.html

4、依赖注入具体案例

有两个组件A和B,A依赖于B。假设A是一个类,且A有一个方法importantMethod用到了B,如下:

class B{
    public void usefulMethod() {}
}

public class A{
    public void importantMethod() {
        //get an instance of B
        B b = new B();
        b.usefulMethod();
    }
}

要使用B,类A必须先获得组件B的实例引用。若B是一个具体类,则可通过new 关键字之间创建组件B的实例。但是,如果B是接口,且有多个实现,则问题就变得复杂了。我们固然可以任意选择接口B的一个实现类,但是这意味着A的可重用性大大降低了,因为无法采用B的其他实现。

依赖注入是这样处理此类情景的:接管对象的创建工作,并将该对象的引用注入到需要该对象的组件中。以上述情况为例,依赖注入框架会分别创建对象A和对象B,然后将对象B注入到对象A中。

为了能让框架进行依赖注入,程序员需要编写特定的set方法或者构造方法。例如,为了能将B注入到A中,类A会被修改成如下形式:

public class A{
    private B b;
    public void importantMethod() {                
        b.usefulMethod();
    }
    
    public void setB(B b) {
        this.b = b;
    }
}

修改后的类A新增了一个set方法,该方法将会被框架调用,以注入B的一个实例。由于对象依赖由依赖注入,类A的importantMethod()方法不再需要在调用B的usefulMethod()方法前去创建B的一个实例。

当然,也可以采用构造器方式注入,如下所示:

public class A{
    private B b;
    
    public A(B b) {
        this.b = b;
    }
    
    public void importantMethod() {                
        b.usefulMethod();
    }    
}

本例中,Spring会先创建B的实例,再创建A的实例,然后把B注入到实例中。

注:Spring管理的对象称为beans。

通过提供一个Ioc容器(或者说DI容器),Spring为我们提供一种可以“聪明”的管理Java对象依赖关系的方法。其优雅之处在于,程序员无需了解Spring框架的存在,更不需要引入任何Spring类型。

5、ApplicationContext接口

使用Spring,程序几乎将所有重要对象的创建工作移交给Spring,并配置如何注入依赖。Spring支持XML或注解两种配置方式。此外,还需要创建一个ApplicationContext对象,代表一个Spring IoC容器,org.springframework.context.ApplicationContext接口有很多实现类,包括ClassPathXmlApplicationContext和FileSystemXmlApplicationContext。这两个实现都需要至少一个包含beans信息的XML文件。

  • ClassPathXmlApplicationContext:尝试在类加载路径中加载配置文件;
  • FileSystemXmlApplicationContext:从文件系统中加载配置路径。
/*
 * Copyright 2002-2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.context;

import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.lang.Nullable;

/**
 * Central interface to provide configuration for an application.
 * This is read-only while the application is running, but may be
 * reloaded if the implementation supports this.
 *
 * <p>An ApplicationContext provides:
 * <ul>
 * <li>Bean factory methods for accessing application components.
 * Inherited from {@link org.springframework.beans.factory.ListableBeanFactory}.
 * <li>The ability to load file resources in a generic fashion.
 * Inherited from the {@link org.springframework.core.io.ResourceLoader} interface.
 * <li>The ability to publish events to registered listeners.
 * Inherited from the {@link ApplicationEventPublisher} interface.
 * <li>The ability to resolve messages, supporting internationalization.
 * Inherited from the {@link MessageSource} interface.
 * <li>Inheritance from a parent context. Definitions in a descendant context
 * will always take priority. This means, for example, that a single parent
 * context can be used by an entire web application, while each servlet has
 * its own child context that is independent of that of any other servlet.
 * </ul>
 *
 * <p>In addition to standard {@link org.springframework.beans.factory.BeanFactory}
 * lifecycle capabilities, ApplicationContext implementations detect and invoke
 * {@link ApplicationContextAware} beans as well as {@link ResourceLoaderAware},
 * {@link ApplicationEventPublisherAware} and {@link MessageSourceAware} beans.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @see ConfigurableApplicationContext
 * @see org.springframework.beans.factory.BeanFactory
 * @see org.springframework.core.io.ResourceLoader
 */
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
        MessageSource, ApplicationEventPublisher, ResourcePatternResolver {

    /**
     * Return the unique id of this application context.
     * @return the unique id of the context, or {@code null} if none
     */
    @Nullable
    String getId();

    /**
     * Return a name for the deployed application that this context belongs to.
     * @return a name for the deployed application, or the empty String by default
     */
    String getApplicationName();

    /**
     * Return a friendly name for this context.
     * @return a display name for this context (never {@code null})
     */
    String getDisplayName();

    /**
     * Return the timestamp when this context was first loaded.
     * @return the timestamp (ms) when this context was first loaded
     */
    long getStartupDate();

    /**
     * Return the parent context, or {@code null} if there is no parent
     * and this is the root of the context hierarchy.
     * @return the parent context, or {@code null} if there is no parent
     */
    @Nullable
    ApplicationContext getParent();

    /**
     * Expose AutowireCapableBeanFactory functionality for this context.
     * <p>This is not typically used by application code, except for the purpose of
     * initializing bean instances that live outside of the application context,
     * applying the Spring bean lifecycle (fully or partly) to them.
     * <p>Alternatively, the internal BeanFactory exposed by the
     * {@link ConfigurableApplicationContext} interface offers access to the
     * {@link AutowireCapableBeanFactory} interface too. The present method mainly
     * serves as a convenient, specific facility on the ApplicationContext interface.
     * <p><b>NOTE: As of 4.2, this method will consistently throw IllegalStateException
     * after the application context has been closed.</b> In current Spring Framework
     * versions, only refreshable application contexts behave that way; as of 4.2,
     * all application context implementations will be required to comply.
     * @return the AutowireCapableBeanFactory for this context
     * @throws IllegalStateException if the context does not support the
     * {@link AutowireCapableBeanFactory} interface, or does not hold an
     * autowire-capable bean factory yet (e.g. if {@code refresh()} has
     * never been called), or if the context has been closed already
     * @see ConfigurableApplicationContext#refresh()
     * @see ConfigurableApplicationContext#getBeanFactory()
     */
    AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;

}
View Code

相关文章:

  • 2022-01-24
  • 2021-05-02
  • 2022-02-08
  • 2022-03-10
  • 2022-12-23
  • 2022-12-23
  • 2022-02-12
  • 2022-12-23
猜你喜欢
  • 2021-07-28
  • 2021-06-15
  • 2021-12-21
  • 2021-07-29
  • 2021-05-30
  • 2021-05-06
相关资源
相似解决方案