【JavaWeb_Part07】功能堪比 502 的强大粘合剂?Spring(春天)框架表演秀
来源:互联网 发布:tf卡测速软件 编辑:程序博客网 时间:2024/04/28 22:32
前面我们已经讲完了 Dao 层(也就是持久层框架 mybatis )在开发中的大部分主要功能,秉承着中华上下五千年不太监的原则,本该这篇文章应该是写表现层框架的,经过我辗转反侧,夜不能寐的思考后,我决定还是排队来,先来写一下传说中后台开发的 502 神器-Spring,也就是春天这个框架。(PS:听说 Hibernate 是冬天,不信你去查 - -!)
老规矩,开篇还是说了一堆废话,讲框架,我们还是从入门开始讲起。Spring 的来源就不说了,不知道的出门左转百度百科。
为啥要学 Spring 框架呢?这里从百度爹爹那里抄来了一段话:你们将就着看。
1. 方便解耦,简化开发
Spring就是一个大工厂,可以将所有对象创建和依赖关系维护,交给Spring管理。
2. AOP编程的支持
Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能。
3. 声明式事务的支持
只需要通过配置就可以完成对事务的管理,而无需手动编程。
4. 方便程序的测试
Spring对Junit4支持,可以通过注解方便的测试Spring程序。
5. 方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts2、Hibernate、MyBatis、Quartz等)的直接支持。
6. 降低JavaEE API的使用难度
Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低。
看完上面的一段话不知道你们有什么感慨,反正劳资就是 45° 抬头,抽了一口烟,心里一万只草泥马呼啸而过,这他妈讲的些什么玩意。看不懂也没啥关系,反正劳资会用,是骡子是马拉出来遛遛就行了,懂那么多理论干嘛?又不能当饭吃。
好了,言归正传,直接开撸春天的入门程序。
Spring 入门
上次我们说 mybatis 的时候,第一步是干啥来着?搭环境?劳资一巴掌呼死你,还不赶紧去官网下 Spring ? Spring 都没有,搭尼玛的个锤子环境。
下载自己去百度搜索,本人比较懒,就不说 Spring 的下载了,不会的送你们一张图。
1. Spring 环境准备
下载下来 Spring 后,解压出来,你应该可以看到是这样的一个文件夹。
我这里的版本是 4.2 的,所以我就以 4.2 为基础开始记录了。里面有四个文件夹。
-schema 表示约束头(不懂没关系,去无脑百度就行了)-docs 这个就容易多了,文档呗。只不过和 mybatis 有点不同。什么?你不懂?那你滚吧。-dependencies 这个就是 spring 所需要的一些依赖。最后一个就是 spring 的文件夹咯。
点开 spring 文件夹,有如下的目录结构。
spring 核心的一些 jar 包全部在 spring 目录下,lib 下面包含了 spring 全部的 jar 包。
按规矩,我们还是由浅入深开始讲解。
2. 搭建简单 Spring 运行环境
新建 java 工程,拷贝最简单的 Spring jar 到 lib 目录下,所需要的 jar 包主要有如下 6 个。
beans 和 context 以及 core,expression 是 Spring 运行环境必须的 4 个jar 包,这个从文档中的图我们就可以看出来端倪。至于另外两个就是日志文件咯。依然还是 log4j。log4j 记得从 -dependencies 目录下去找。
看下面的 Core Container ,很明显就说了 4 个模块,每个模块对应的就是一个 jar 包。这个图示从文档上找来的,想看的话,自己去文档里面翻。(SpEL 就是 Spring Expression Spring 表达式)
jar 包现在已经有了,那么我们是不是就可以直接运行 Hello World 了呢?呸呸呸,明明是 Hello Spring。显然不能,我们还缺少一样致命的东西,记得我们讲 Mybatis 的时候,除了拷贝 jar 包,还做了一些什么了么?没错,核心配置文件,任何框架都有自己的核心配置文件,Spring 也同样有自己的配置文件-ApplicationContext.xml。(温馨提示:这个文件的名字不是固定的,但是还是不要改,因为开发中都是使用的这个名字。)
在 src 目录下新建文件,命名为 ApplicationContext.xml,有常识的人都知道,xml 前面应该有一个约束,Spring 也有,那么这个约束怎么写呢?别告诉我说你是记下来的,你疯了吧。命名空间你记下来?直接去文档中找不就得了。
动动你昂贵的脑子,直接搜索就可以了。拷贝这部分到 applicationContext.xml 就行了。
3. IOC 乱入
满心期待跑起来 Hello Spring,却发现来了一个 IOC,这又是个什么鬼?嗯。不讲 IOC 的话,显然我们下面无法进行下去。那就先说说 IOC 吧。究竟 IOC 是什么?IOC 全程为 Invocation of Control, 翻译过来就是“控制反转”。那什么又是控制反转呢? 我们来举一个例子。
1. 新建一个接口 UserService 和一个实现类 UserServiceImpl
2. 在 UserService 中定义一个 sayHello() 方法,在 UserServiceImpl 中实现该方法。
//接口中定义的方式public interface UserService { void sayHello();}//实现类中实现的方法public class UserServiceImpl implements UserService { @Override public void sayHello() { System.out.println("hello spring"); }}
新建测试类 TestSpring.java
我们要想调用 sayHello 方法,是不是需要用 new 关键字创建一个 UserServiceImpl 的实例出来?用实例.方法名的方式调用方法?嗯,没错。
@Testpublic void testOld(){ UserService userService = new UserServiceImpl(); userService.sayHello();}
运行的结果我就不贴出来了,太简单。
上面的方式就是传统的方式,嗯,这很优雅。但是你们想一下,这算不算使我们主动创建对象的实例?也就是说创建对象的主动权现在在我们手上。也就是控制正转(PS:不知道有没有这个说法,没有的话就当他是虚构的吧。don’t mind!),既然 Spring 容器提倡控制反转(IOC),那就是就是说我们不应该去占有对象的创建权利,而把创建对象的权利交给 Spring 去帮我们创建。我们只负责调用方法即可。
既然 Spring 去帮我们创建对象,那么我们应该怎么去做呢?首先在 Spring 的配置文件中配置我们需要创建对象的那个类。具体配置如下:
<bean id ="userService" class="com.student.spring.service.UserServiceImpl"/>
class 是我们创建对象的全路径名称, id 是给这个实例取一个名字。切记 class 这里需要填写实现类的全路径。
最后在测试类中写上我们的新的测试方法:
@Testpublic void TestNew(){ //创建工厂 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); //获取对象 UserService userService = (UserService) applicationContext.getBean("userService"); //调用方法 userService.sayHello();}
运行截图如下
到这里,我们的 Hello Spring 就已经完成了,我们没有通过 new 关键字来生成过 UserServiceImpl 对象的实例,但是 sayHello 中的打印信息确实是打印出来了。这说明 Spring 帮我们做了创建对象这一个过程。
ApplicationContext.xml 配置文件详解
目前我们的配置文件中只有
<bean id="userService" class="com.student.spring.service.UserServiceImpl"/>
这样一行代码,实际上 bean 的标签中还有一些其他的标签属性,例如
Scope
init-method
destroy-method
其中 scope 是代表范围的意思,我们都知道单例模式,如果我想让 Spring 帮我们生成的 UserServiceImpl 实例是单例或者多例的,便可以配置
//在 Spring 框架整合 Struts2 框架的时候,Action 类也需要交给 Spring 做管理,配置把 Action 类配置成多例!!scope="singleton" //单例scope="prototype" //多例
后面的 init-method 和 detroy-method 实际上就是初始化方法和销毁方法
比如我们可以在 UserServiceImpl 中添如下两个方法:
public class UserServiceImpl implements UserService { @Override public void sayHello() { System.out.println("hello spring"); } public void initMethod(){ System.out.println("执行初始化"); } public void destroyMethod(){ System.out.println("销毁"); }}
在配置文件中加上
<bean id="userService" class="com.student.spring.service.UserServiceImpl" init-method="initMethod" destroy-method="destroyMethod"/>
执行结果
见图知意,我就不过多解释了。
对了,如果你要看到上图的效果,必须手动调用 Spring 工厂的 close() ,方法,不然 Spring 工厂是不会自动关闭的。同时还必须使用 ApplicationContext 的实现类 ClassPathXmlApplicationContext 去创建工厂。因为 ApplicationContext 这个接口中是没有 close 方法的。
Spring 依赖注入(Injection Dependencies)
依赖注入(DI) 也是 Spring 框架的核心之一,可能你不太理解依赖注入,没关系,我们先来看一个例子。很多时候,我们开发项目都是使用 MVC 的开发模式,MVC 开发模式分为三层:表现层调用业务层,业务层调用 dao 层。那么我们很容易写出如下代码:(几个接口就不写出来了,就是方法声明)
UserDaoImpl.java
public class UserDaoImpl implements UserDao { @Override public void save() { System.out.println("dao 层操作数据库去保存用户数据"); }}
UserServiceImpl.java
public class UserServiceImpl implements UserService { @Override public void save() { System.out.println("业务层操作 Dao 去保存用户"); new UserDaoImpl().save(); }}
测试方法和结果就直接看图吧。
传统的方式都是依靠 new 关键字来创建对象的。比如测试方法和 UserServiceImpl 类中。
UserService userService = new UserServiceImpl();new UserDaoImpl().save();
但是现在我们学了 Spring 的 IOC 功能,我们就可以把创建对象的功能交给 Spring 容器。UserServiceImpl 和 UserDaoImpl 的创建对象任务都交给 Spring 去管理。那么我们需要在配置文件中配置如下两个 bean 对象。
<bean id="userService" class="com.student.spring.service.UserServiceImpl"/> <bean id="userDao" class="com.student.spring.dao.UserDaoImpl"/>
既然这样,那么问题来了,UserServiceImpl 中需要依赖 UserDaoImpl 的实例去调用 save 方法,那么我们就需要在 UserServiceImpl 中生成一个 UserDaoImpl 的实例,那么怎么生成呢?Spring 作为一个功能强大的框架,自然能够帮我们做到这点。
我们更改 UserServiceImpl 中的代码
public class UserServiceImpl implements UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Override public void save() { System.out.println("业务层操作 Dao 去保存用户"); userDao.save(); }}
UserServiceImpl 需要一个 UserDaoImpl 的实例,我们就通过配置文件给它注入一个就好。继续更改我们的配置文件:
<bean id="userService" class="com.student.spring.service.UserServiceImpl"> <property name="userDao" ref="userDao1"/></bean><bean id="userDao1" class="com.student.spring.dao.UserDaoImpl"/>
property 中的 name 就是我们定义的成员变量的名称
property 中的 ref 就是我们下面定义的 bean 中的 id
property 中除了 ref 之外,还有一种选值 value。value 是给基本数据类型赋值所用的。
上面的配置就体现了 Spring 框架的依赖注入功能。运行结果:
UserServiceImpl 中需要一个 UserDaoImpl,我们利用配置文件给它注入了一个 UserDaoImpl 实例。那为什么要生成 set 方法呢?在配置文件中配置的默认注入方式就是 set 方法,如果你没有 set 方法,那么注入一定会失败。有兴趣的可以自己去试试。注入有很多种方式,我们后面来讲解。
还记得上面说了一个 ref 和 value 么?现在我们来试一试 value。
在 UserServiceImpl 中添加成员变量 name,提供 set 方法。
private String name;public void setName(String name) { this.name = name; }
配置文件中做如下更改:
<bean id="userService" class="com.student.spring.service.UserServiceImpl"> <property name="userDao" ref="userDao"/> <property name="name" value="楚乔"/></bean><bean id="userDao" class="com.student.spring.dao.UserDaoImpl"/>
输出结果:
这样是不是就一目了然了?
value 是给属性注入值(一般应用于基本数据类型)
ref 是给属性注入引用(一般应用于引用类型)
4. 总结
IOC 和 DI 的概念
IOC: Inverse of Control,控制反转,将对象的创建权反转给 Spring !
DI:Dependency Injection,依赖注入,在 Spring 框架负责创建 Bean 对象时,动态的将依赖对象注入到 Bean 组件中!
DI(依赖注入)
例如:如果 UserServiceImpl 的实现类中有一个属性,那么使用 Spring 框架的 IOC 功能时,可以通过依赖注入把该属性的值传入进来!
具体的配置如下
结语
依赖注入的方式有很多,但是主流的注入方式始终只有一两种,我们也只打算讲一两种,其他的如果你们有兴趣,可是去试试。
1. Set 方法注入(☆☆☆☆)
2. 构造函数注入(☆☆)
3. 注解注入(☆☆☆☆☆)
4. p 名称空间注入(☆)
5. SpEL 注入方式注入(☆)
后面的星星代表优先级,我们今天讲的注入方式就是通过 set 方式注入,本来想讲一下这几种注入方式的,但是看了一下篇幅,好像废话有点多,导致篇幅过长,那今天就先暂时到这里吧。依赖注入的几种方式我们留到下一节再去讲解。主要讲前三种注入方式,从星星的数量上来说,你们应该也知道哪些注入方式比较重要。今天就到这里吧,能力有限,写出来的东西难免有错误,如果有错误,还希望各位不吝指正。同时也欢迎小伙伴们留言交流。
- 【JavaWeb_Part07】功能堪比 502 的强大粘合剂?Spring(春天)框架表演秀
- Spring之开源框架的春天
- 比Picasso更强大的框架----Glide
- 比Picasso更强大的框架Glide
- Spring程序员的春天
- spring带来的春天
- spring框架的功能
- Spring 框架的 UI(IOC) 功能
- Spring-春天的故事1
- spring-春天的故事2
- 秋天里的春天-spring笔记(一)
- 秋天里的春天-spring笔记(二):IoC
- Android图片加载框架最全解析(五),Glide强大的图片变换功能
- Android图片加载框架最全解析(五),Glide强大的图片变换功能
- Android图片加载框架最全解析(五),Glide强大的图片变换功能
- Android 图片加载框架最全解析(五),Glide强大的图片变换功能
- Android图片加载框架最全解析(五),Glide强大的图片变换功能
- Android图片加载框架最全解析(五),Glide强大的图片变换功能
- React native全局变量的使用(跨组件的通信)
- 观察者模式
- 为什么要写《机器学习实践应用》这本书
- 二维表和一维表在Spotfire中的可视化差异
- HDU5536-暴力|01字典树-J
- 【JavaWeb_Part07】功能堪比 502 的强大粘合剂?Spring(春天)框架表演秀
- 20170702 正阳门下
- 使用ssh协议在github服务器和本机之间进行数据传输
- Java中10大常见异常
- MYSQL权限
- [牛客网,剑指offer,python] 跳台阶
- 客户端的配置与应用
- gdb下的多进程多线程的调试
- 引用与指针