目录

什么是Spring?

为什么学习Spring?

Spring的快速入门

Spring的版本

IOC概述

什么是IOC?

Spring的IoC入门

下载Spring的开发包

创建web项目,引入Spring的开发包

创建接口和实现类

编写测试类

Spring IoC和DI的区别


什么是Spring?

Spring是一个轻量级的Java开发框架。Spring的核心是控制反转(IoC)和面向切面(AOP),简单来说,Spring是一个分层的JavaSE/EEfull-stack(一站式)轻量级开源框架。

为什么说Spring是一个一站式的轻量级开源框架呢?EE开发可分成三层架构,针对JavaEE的三层结构,每一层Spring都提供了不同的解决技术。

从对Spring的简要介绍中,我们知道了Spring的核心有两部分:

IoC:即控制反转。举例来说,在之前的操作中,比方说有一个类,我们想要调用类里面的方法(不是静态方法),就要创建该类的对象,使用对象调用方法来实现。但对于Spring来说,Spring创建对象的过程,不是在代码里面实现的,而是交给Spring来进行配置实现的;
AOP:即面向切面编程。之前,讲Struts2框架的拦截器时,我们就已稍微讲了一下,在Spring后续的学习过程中,我们会着重来讲它,但是本文并不会过多阐述它。

为什么学习Spring?

1)方便解耦,简化开发

通过Spring提供的IOC容器,我们可以将对象之间的依赖关系交给Spring进行控制,避免硬编码所造成的的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。

2)AOP编程的支持

通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应对。

3)声明式事务的支持

在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务的管理,提高开发效率和质量。

4)方便程序的测试

可以用废容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不在是昂贵的操作,二十随手可做的事情。例如:Spring对Junit4支持,可以通过注解方便地测试Spring程序。

5)方便集成各种优秀框架

Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了各种优秀框架(如Struts\Hibernate\Hessian\Quartz)等的直接支持。

6)降低Java EE API的使用难度

Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,通过Spring的简易封装,这些Java EE API的使用难度大为降低。

Spring的快速入门

Spring的版本

需要说明的是,本系列入门Spring的教程使用的版本是spring-framework-4.2.4.RELEASE。

IOC概述

什么是IOC?

IoC即Inversion of Control,反应过来就是控制反转。啥是控制反转啊?控制反转指的就是将对象的创建权反转给(交给)了Spring,其作用是实现了程序的解耦合。也可这样解释:获取对象的方式变了,对象创建的控制权不是"使用者",而是"框架"或者"容器"。用更通俗的话来说,IoC就是指对象的创建,并不是在代码中用new操作new出来的,而是通过Spring进行配置创建的。

Spring的IoC的底层实现原理
这里先给出结论:Spring的IoC的底层实现原理是工厂设计模式+反射+XML配置文件。 就拿持久层(也即dao层,data access object,数据访问对象)的开发来说,官方推荐做法是先创建一个接口,然后再创建接口对应的实现类。所以,这里,我会以dao层的开发为例来证明Spring的IoC的底层实现原理就是工厂设计模式+反射+XML配置文件。

首先,创建一个Userdao接口。

public interface UserDao {public void add();
}

然后,再创建Userdao接口的一个实现类(UserDaoImpl.java)。

public class UserDaoImpl implements UserDao {public void add() {balabala......}
}

接着,我们在service层中调用dao层,核心代码如下:

// 接口 实例变量 = new 实现类
UserDao dao = new UserDaoImpl();
dao.add();

这时我们便可发现一个缺点:service层和dao层耦合度太高了,即接口和实现类有耦合(它俩之间的联系过于紧密),一旦切换底层实现类,那么就需要修改源代码,这真的不是一个好的程序设计,好的程序设计应当满足OCP原则(也即开闭原则),即在尽量不修改程序源代码的基础上对程序进行扩展。

出现的这个问题该如何解决呢?解决方法是使用工厂设计模式进行解耦合操作。所以,我们需要创建一个工厂类,在工厂类中提供一个方法,返回实现类的对象。

public class BeanFactory {// 提供返回实现类对象的方法public static UserDao getUserDao() {return new UserDaoImpl();}
}

这样,在service层中调用dao层的核心代码就变为了下面的样子。

UserDao dao = BeanFactory.getUserDao();
dao.add();

如若这样做,会发现又产生了一个缺点:现在接口和实现类之间是没有耦合了,但是service层和工厂类耦合了。如果真正想实现程序之间的解耦合,那么就需要使用到工厂设计模式+反射+XML配置文件了。所以,我们这里提供一个XML配置文件,并且该配置文件中有如下配置信息。

<bean id="userDao" class="com.meimeixia.dao.impl.UserDaoImpl" />

然后再来创建一个工厂类,在工厂类中提供一个返回实现类对象的方法,但并不是直接new实现类,而是使用SAX解析配置文件,根据标签bean中的id属性值得到对应的class属性值,使用反射创建实现类对象。

public class BeanFactory {public static Object getBean(String id) {// 1.使用SAX解析得到配置文件内容// 直接根据id值userDao得到class属性值String classvalue = "class属性值";// 2.使用反射得到对象Class clazz = Class.forName(classvalue);UserDaoImpl userDaoImpl = (UserDaoImpl)lazz.newInstance();return userDaoImpl;}
}

以上就是Spring的IoC的底层实现原理。

Spring的IoC入门

下载Spring的开发包

Spring的官网是https://spring.io/,Spring的开发包的下载地址是https://repo.spring.io/libs-release-local/org/springframework/spring/,上面说过,我下载的是spring-framework-4.2.4.RELEASE这个版本的Spring。解压缩之后,可发现Spring开发包的目录结构如下。

创建web项目,引入Spring的开发包

首先创建一个动态web项目,例如spring_demo01,然后导入Spring框架相关依赖jar包,要导入哪些jar包呢?这是一个问题。

由于我们只是初次入门Spring,所以也只是使用到了Spring的基本功能,从上图红框框中的部分可知,我们需要使用到下面的这4个jar包。

除此之外,还要导入Spring支持的日志jar包,也就是下面两个jar包。

关于以上两个jar包,我稍微做一下解释,com.springsource.org.apache.commons.logging-1.1.1.jar它里面都是一些接口,有接口,那当然要有实现类了,恰好,com.springsource.org.apache.log4j-1.2.15.jar里面就是那些接口的实现类。使用Log4j,我们可以查看到当前运行程序中对象创建的过程,也可以看到更详细的信息,Log4j适合使用在程序调试中。
导入完日志相关的jar包之后,我们还要导入日志记录文件,即在src目录下引入Log4j的配置文件(log4j.properties),该文件内容如下:

### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c\:mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n### set log levels - for more verbose logging change 'info' to 'debug' ###
# error warn info debug trace
log4j.rootLogger= info, stdout

对以上日志记录文件,我会粗略讲解一下。

从上图可知,log4j.rootLogger就是用于设置日志的输出级别,那么日志的输出级别有几种呢?有如下5种。

创建接口和实现类

首先,在src目录下创建一个com.meimeixia.spring.demo01包,并在该包下创建一个名为UserDao的接口。

package com.meimeixia.spring.demo01;/*** 用户管理的dao层的接口* @author liayun**/
public interface UserDao {public void save();}

然后,在com.meimeixia.spring.demo01包下创建UserDao接口的一个实现类——UserDaoImpl.java。

package com.meimeixia.spring.demo01;
/*** 用户管理的dao层接口的实现类* @author liayun**/
public class UserDaoImpl implements UserDao {@Overridepublic void save() {System.out.println("UserDaoImpl中的save方法执行了......");}
}

将实现类交给Spring管理
首先,我们需要创建Spring的配置文件,Spring配置文件的名称和位置没有固定要求,一般建议把该文件放到src目录下面,名称可随便写,官方建议写成applicationContext.xml。然后我们还需要在配置文件中引入约束,Spring学习阶段的约束是schema约束。那么问题来了,这个约束又该怎么写呢?可参考docs\spring-framework-reference\html目录下的xsd-configuration.html文件,在其内容最后面找到如下内容。

将其复制黏贴到配置文件applicationContext.xml中,这样applicationContext.xml文件的内容就是下面的样子了。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"></beans>

最后,咱还要将实现类交给Spring来管理,即在配置文件中配置对象的创建。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- Spring入门的配置 --><bean id="userDao" class="com.meimeixia.spring.demo01.UserDaoImpl"></bean></beans>

编写测试类

我们要在Spring中写代码来实现获取applicationContext.xml文件中配置的对象,这段代码不要求大家重点掌握,只是用在测试中而已。这段代码主要用来解析Spring配置文件得到对象,但这个过程不需要我们写代码来实现了,Spring已经封装了一个对象来帮我们进行了这些操作,这个对象叫ApplicationContext,它就能实现这个功能。于是,我们需要在com.meimeixia.spring.demo01包下创建一个SpringDemo01的单元测试类。

package com.meimeixia.spring.demo01;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;/*** Spring的入门* @author liayun**/
public class SpringDemo01 {/** 传统方式的调用*/@Testpublic void demo01() {UserDao userDao = new UserDaoImpl();userDao.save();}/** Spring的方式的调用*/@Testpublic void demo02() {//先要创建Spring的工厂ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");// classpath就是类路径,src目录下的文件最终要编译到类路径下UserDao userDao = (UserDao) applicationContext.getBean("userDao");userDao.save();}}

然后,运行以上demo02单元测试方法,Eclipse控制台就会打印如下内容。

注意:这里的applicationContext.xml是放在src下,可运行成功,否则下面这句话会报错。

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

Spring IoC和DI的区别

IoC上面我已经讲过了,它指的就是将对象的创建权反转给(交给)了Spring。那DI又是什么鬼呢?DI,即Dependency Injection,翻译过来就是依赖注入,它指的就是Spring在管理某个类的时候会将该类依赖的属性注入(设置)进来,也就是说在创建对象的过程中,向类里面的属性中设置值。注意:依赖注入不能单独存在,须在控制反转基础之上完成,用更通俗点的话来说,就是注入类里面的属性值,不能直接注入,须创建类的对象再完成注入。
你还记得在面向对象设计的时候,类和类之间有几种关系吗?有3种,它们分别是:

  • 依赖,由于下图中B类的方法用到了A类,所以此时就可以说B类依赖于A类;
  • 继承(is a),这种关系我们应该是见的要吐了;
  • 聚合(has a),它有松散和紧密之分。例如,球队得有一个守门员,即使这个球队没有了这个守门员,它也还是一个球队,所以它是松散的;人得有一个脑袋,此时它就是紧密的。

说了这么多,咱就通过一个案例来看看DI在程序的体现。现在,我们想要给UserDaoImpl这个实现类里面的某一个属性(例如String类型的name)设置值,该咋怎呢?首先,将UserDaoImpl这个实现类修改成下面这个样子。

package com.meimeixia.spring.demo01;
/*** 用户管理的dao层接口的实现类* @author liayun**/
public class UserDaoImpl implements UserDao {private String name;//提供set方法public void setName(String name) {this.name = name;}@Overridepublic void save() {System.out.println("UserDaoImpl中的save方法执行了......" + name);}
}

如果使用传统的方式来为UserDaoImpl实现类的name属性设置值,那么SpringDemo01单元测试类中的demo01方法就应该写成下面这个样子。

package com.meimeixia.spring.demo01;import org.junit.Test;
/*** Spring的入门* @author liayun**/
public class SpringDemo01 {/** 传统方式的调用*/@Testpublic void demo01() {/** 我想给这个类里面的某一个属性设置值,挺麻烦的!* * 1. 不能面向接口编程了* 2. 你还得手动调用set方法,也得去改变程序的源代码*/UserDaoImpl userDao = new UserDaoImpl();userDao.setName("李二");userDao.save();}
}

这样写,就有两个缺点,一是不能面向接口编程了,二是咱还得手动调用对象的set方法,这必然就涉及到要改变程序的源代码了,这是我们不能接受的!
如果使用了依赖注入,即在applicationContext.xml文件中为配置好的UserDaoImpl实现类的name属性注入一个值,那么情况就完全不同了,以上两个缺点也就不复存在了。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- Spring入门的配置 --><bean id="userDao" class="com.meimeixia.spring.demo01.UserDaoImpl"><!-- DI:依赖注入 --><property name="name" value="李二" /></bean>
</beans>

此时,SpringDemo01单元测试类中的demo02方法依然不变,如下。

package com.meimeixia.spring.demo01;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;/*** Spring的入门* @author liayun**/
public class SpringDemo01 {/** 传统方式的调用*/@Testpublic void demo01() {        /** 我想给这个类里面的某一个属性设置值,挺麻烦的!* * 1. 不能面向接口编程了* 2. 你还得手动调用set方法,也得去改变程序的源代码*/UserDaoImpl userDao = new UserDaoImpl();userDao.setName("李二");userDao.save();}/** Spring的方式的调用*/@Testpublic void demo02() {//先要创建Spring的工厂ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");UserDao userDao = (UserDao) applicationContext.getBean("userDao");userDao.save();}
}

运行以上demo02单元测试方法,Eclipse控制台就会打印出如下内容。


版权声明:本文为CSDN博主「李阿昀」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yerenyuan_pku/article/details/69663685

Spring框架快速入门相关推荐

  1. 视频教程-Spring框架快速入门到精通-Java

    Spring框架快速入门到精通 十年项目开发经验,主要从事java相关的开发,熟悉各种mvc开发框架. 王振伟 ¥18.00 立即订阅 扫码下载「CSDN程序员学院APP」,1000+技术好课免费看 ...

  2. Spring框架快速入门(Spring超全面讲解)

    Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用. 本课程将深入浅出讲解Spring的核心技术IoC.AOP,剖析框架 ...

  3. Quartz 框架快速入门(四)

    Spring的scheduling.quartz包中对Quartz框架进行了封装,使得开发时不用写任何QuartSpring的代码就可以实现定时任务.Spring通过JobDetailBean,Met ...

  4. 视频教程-Spring boot快速入门-Java

    Spring boot快速入门 十年项目开发经验,主要从事java相关的开发,熟悉各种mvc开发框架. 王振伟 ¥12.00 立即订阅 扫码下载「CSDN程序员学院APP」,1000+技术好课免费看 ...

  5. Quartz 框架快速入门(二)

    尽可能的用声明式处理软件配置,其次才考虑编程式的方式.在上一篇<Quartz 框架快速入门(一)>中,如果我们要在 Job 启动之后改变它的执行时间和频度,必须去修改源代码重新编译.这种方 ...

  6. Quartz 框架快速入门(三)

    在前面两篇文章中简单介绍了在java应用程序中如何使用Quartz框架,这一篇中我们将看到如何在web环境下通过配置文件来完成Quartz的后台作业调度,而不必手工去创建Trigger和Schedul ...

  7. 【完结】给新手的12大深度学习开源框架快速入门项目

    文/编辑 | 言有三 这是一篇总结文,给大家来捋清楚12大深度学习开源框架的快速入门,这是有三AI的GitHub项目,欢迎大家star/fork. https://github.com/longpen ...

  8. java day53【 Mybatis框架概述 、 Mybatis 框架快速入门、自定义 Mybatis 框架 】

    第1章 框架概述 1.1 什么是框架 1.1.1 什么是框架 框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种 定义认为,框架是可被应用开发者定 ...

  9. spring boot 快速入门

    文章来源:https://www.cnblogs.com/junyang/p/8151802.html spring boot入门 -- 介绍和第一个例子 "越来越多的企业选择使用sprin ...

最新文章

  1. 阿里程序员35岁P7!4年了晋升无望!明年股票拿完,年包腰斩!世界那么大,要不要去看看?...
  2. Struts 源码分析笔记1(尚无内容-请跳过,省得浪费时间)
  3. android技术下载
  4. 全球及中国冶金工业运行潜力与深度战略分析报告2022版
  5. t test table
  6. 为什么开了数据不能上网_Doinb和LCK选手双排为什么不能开语音?Doinb深夜道出实情...
  7. Hermes与开源的Solr、ElasticSearch的不同
  8. 20-forEach循环语句
  9. 关于eclipse项目红色感叹号的解决办法
  10. 石子合并问题--直线版(Hrbust-1818)
  11. 动画片动漫迷<未来的未来>高清图片壁纸
  12. 查看IIS进程所对应的应用程序池名称
  13. (20190401)IGS GNSS数据下载网址与下载说明
  14. 怎么隐藏电脑桌面计算机,电脑怎么隐藏桌面图标?
  15. 调试bootmgrwinload vistawin7 x86x64
  16. Windows应用商店下载安装Ubuntu
  17. 信息收集之网站镜像克隆
  18. Python中文分词库jieba用法代码示例
  19. 1155 服务器芯片组,2014年主流主板芯片组分析
  20. 批量取消bilibili关注

热门文章

  1. 在实体引用中,实体名称必须紧跟在 ‘’后面
  2. Android的WebView如何播放视频和全屏视频(腾讯X5内核)
  3. 轻量应用服务器 饥荒,饥荒服务端世界设置生成
  4. mcs51单片机嵌入式c语言习题,MCS-51单片机复习题参考题库.doc
  5. 普中tft彩屏驱动程序下载_tft彩屏驱动程序
  6. SecureBoost: A Lossless Federated Learning Framework论文笔记
  7. 一篇文章读懂《麦肯锡极简工作法》
  8. UG模具:简单的运动仿真!只需七步,就让轮子转起来!
  9. Golang DNS 随便写写
  10. java基础多线程抢红包_java多线程模拟抢红包功能