Spring的模块化是很强的,各个功能模块都是独立的,我们可以选择的使用。这一章先从Spring的IoC开始。所谓IoC就是一个用XML来定义生成对象的模式,我们看看如果来使用的。
数据模型
1、如下图所示有三个类,Human(人类)是接口,Chinese(中国人)是一个子类,American(美国人)是另外一个子类。
源代码如下:
java 代码
package cn.com.chengang.spring;
public interface Human {
void eat();
void walk();
}
package cn.com.chengang.spring;
public class Chinese implements Human {
/* (非 Javadoc)
* @see cn.com.chengang.spring.Human#eat()
*/
public void eat() {
System.out.println("中国人对吃很有一套");
}
/* (非 Javadoc)
* @see cn.com.chengang.spring.Human#walk()
*/
public void walk() {
System.out.println("中国人行如飞");
}
}
package cn.com.chengang.spring;
public class American implements Human {
/* (非 Javadoc)
* @see cn.com.chengang.spring.Human#eat()
*/
public void eat() {
System.out.println("美国人主要以面包为主");
}
/* (非 Javadoc)
* @see cn.com.chengang.spring.Human#walk()
*/
public void walk() {
System.out.println("美国人以车代步,有四肢退化的趋势");
}
}
2、对以上对象采用工厂模式的用法如下
创建一个工厂类Factory,如下。这个工厂类里定义了两个字符串常量,所标识不同的人种。getHuman方法根据传入参数的字串,来判断要生成什么样的人种。
java 代码
package cn.com.chengang.spring;
public class Factory {
public final static String CHINESE = "Chinese";
public final static String AMERICAN = "American";
public Human getHuman(String ethnic) {
if (ethnic.equals(CHINESE))
return new Chinese();
else if (ethnic.equals(AMERICAN))
return new American();
else
throw new IllegalArgumentException("参数(人种)错误");
}
}
下面是一个测试的程序,使用工厂方法来得到了不同的“人种对象”,并执行相应的方法。
java 代码
package cn.com.chengang.spring;
public class ClientTest {
public static void main(String[] args) {
Human human = null;
human = new Factory().getHuman(Factory.CHINESE);
human.eat();
human.walk();
human = new Factory().getHuman(Factory.AMERICAN);
human.eat();
human.walk();
}
}
3、采用Spring的IoC的用法如下:
在项目根目录下创建一个bean.xml文件
xml 代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="Chinese" class="cn.com.chengang.spring.Chinese"/>
<bean id="American" class="cn.com.chengang.spring.American"/>
</beans>
修改ClientTest程序如下:
java 代码
package cn.com.chengang.spring;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class ClientTest {
public final static String CHINESE = "Chinese";
public final static String AMERICAN = "American";
public static void main(String[] args) {
// Human human = null;
// human = new Factory().getHuman(Factory.CHINESE);
// human.eat();
// human.walk();
// human = new Factory().getHuman(Factory.AMERICAN);
// human.eat();
// human.walk();
ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml");
Human human = null;
human = (Human) ctx.getBean(CHINESE);
human.eat();
human.walk();
human = (Human) ctx.getBean(AMERICAN);
human.eat();
human.walk();
}
}
从这个程序可以看到,ctx就相当于原来的Factory工厂,原来的Factory就可以删除掉了。然后又把Factory里的两个常量移到了ClientTest类里,整个程序结构基本一样。
再回头看原来的bean.xml文件的这一句:
<bean id="Chinese" class="cn.com.chengang.spring.Chinese"/>
id就是ctx.getBean的参数值,一个字符串。class就是一个类(包名+类名)。然后在ClientTest类里获得Chinese对象就是这么一句
human = (Human) ctx.getBean(CHINESE);
因为getBean方法返回的是Object类型,所以前面要加一个类型转换。
总结
(1)也许有人说,IoC和工厂模式不是一样的作用吗,用IoC好象还麻烦一点。
举个例子,如果用户需求发生变化,要把Chinese类修改一下。那么前一种工厂模式,就要更改Factory类的方法,并且重新编译布署。而IoC只需要将class属性改变一下,并且由于IoC利用了Java反射机制,这些对象是动态生成的,这时我们就可以热插拨Chinese对象(不必把原程序停止下来重新编译布署)
(2)也许有人说,即然IoC这么好,那么我把系统所有对象都用IoC方式来生成。
注意,IoC的灵活性是有代价的:设置步骤麻烦、生成对象的方式不直观、反射比正常生成对象在效率上慢一点。因此使用IoC要看有没有必要,我认为比较通用的判断方式是:用到工厂模式的地方都可以考虑用IoC模式。
(3)在上面的IoC的方式里,还有一些可以变化的地方。比如,bean.xml不一定要放在项目录下,也可以放在其他地方,比如cn.com.chengang.spring包里。不过在使用时也要变化一下,如下所示:
new FileSystemXmlApplicationContext("src/cn/com/chengang/spring/bean.xml");
另外,bean.xml也可以改成其他名字。这样我们在系统中就可以分门别类的设置不同的bean.xml。
(4)关于IoC的低侵入性。
什么是低侵入性?如果你用过Struts或EJB就会发现,要继承一些接口或类,才能利用它们的框架开发。这样,系统就被绑定在Struts、EJB上了,对系统的可移植性产生不利的影响。如果代码中很少涉及某一个框架的代码,那么这个框架就可以称做是一个低侵入性的框架。
Spring的侵入性很低,Humen.java、Chinese.java等几个类都不必继承什么接口或类。但在ClientTest里还是有一些Spring的影子:FileSystemXmlApplicationContext类和ctx.getBean方式等。
现在,低侵入性似乎也成了判定一个框架的实现技术好坏的标准之一。
(5)关于bean.xml的用法
bean.xml的用法还有很多,其中内容是相当丰富的。假设Chinese类里有一个humenName属性(姓名),那么原的bean.xml修改如下。此后生成Chinese对象时,“陈刚”这个值将自动设置到Chinese类的humenName属性中。而且由于singleton为true这时生成Chinese对象将采用单例模式,系统仅存在一个Chinese对象实例。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="Chinese" class="cn.com.chengang.spring.Chinese" singleton="true">
<property name="humenName">
<value>陈刚</value>
</property>
</bean>
<bean id="American" class="cn.com.chengang.spring.American"/>
</beans>
关于bean.xml的其它用法,不再详细介绍了,大家自己拿Spring的文档一看就明白了。
Spring能有效地组织J2EE应用各层的对象。不管是控制层的Action对象,还是业务层的Service对象,还是持久层的DAO对象,都可在Spring的管理下有机地协调、运行。Spring将各层的对象以松耦合的方式组织在一起,Action对象无须关心Service对象的具体实现,Service对象无须关心持久层对象的具体实现,各层对象的调用完全面向接口。当系统需要重构时,代码的改写量将大大减少。
上面所说的一切都得宜于Spring的核心机制,依赖注入。依赖注入让bean与bean之间以配置文件组织在一起,而不是以硬编码的方式耦合在一起。理解依赖注入
依赖注入(Dependency Injection)和控制反转(Inversion of Control)是同一个概念。具体含义是:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在Spring里,创建被调用者的工作不再由调用者来完成,因此称为控制反转;创建被调用者实例的工作通常由Spring容器来完成,然后注入调用者,因此也称为依赖注入。
不管是依赖注入,还是控制反转,都说明Spring采用动态、灵活的方式来管理各种对象。对象与对象之间的具体实现互相透明。在理解依赖注入之前,看如下这个问题在各种社会形态里如何解决:一个人(Java实例,调用者)需要一把斧子(Java实例,被调用者)。
(1)原始社会里,几乎没有社会分工。需要斧子的人(调用者)只能自己去磨一把斧子(被调用者)。对应的情形为:Java程序里的调用者自己创建被调用者。
(2)进入工业社会,工厂出现。斧子不再由普通人完成,而在工厂里被生产出来,此时需要斧子的人(调用者)找到工厂,购买斧子,无须关心斧子的制造过程。对应Java程序的简单工厂的设计模式。
(3)进入“按需分配”社会,需要斧子的人不需要找到工厂,坐在家里发出一个简单指令:需要斧子。斧子就自然出现在他面前。对应Spring的依赖注入。
第一种情况下,Java实例的调用者创建被调用的Java实例,必然要求被调用的Java类出现在调用者的代码里。无法实现二者之间的松耦合。
第二种情况下,调用者无须关心被调用者具体实现过程,只需要找到符合某种标准(接口)的实例,即可使用。此时调用的代码面向接口编程,可以让调用者和被调用者解耦,这也是工厂模式大量使用的原因。但调用者需要自己定位工厂,调用者与特定工厂耦合在一起。
第三种情况下,调用者无须自己定位工厂,程序运行到需要被调用者时,系统自动提供被调用者实例。事实上,调用者和被调用者都处于Spring的管理下,二者之间的依赖关系由Spring提供。
所谓依赖注入,是指程序运行过程中,如果需要调用另一个对象协助时,无须在代码中创建被调用者,而是依赖于外部的注入。Spring的依赖注入对调用者和被调用者几乎没有任何要求,完全支持对POJO之间依赖关系的管理。依赖注入通常有两种:
·设值注入。
·构造注入。
原文链接:http://java.banzhu.net/article/java-4-158422.html
分享到:
相关推荐
ruoyi-vue-pro-vben 芋道管理后台,基于 vben 最新版本,最新的 vue3 vite4 ant-design-vue 4.0 typescript 语法进行重构开发,支持 springboot3 springcloud 版本
那些年,与你同分同位次的同学都去了哪里?全国各大学在四川2020-2024年各专业最低录取分数及录取位次数据,高考志愿必备参考数据
yolo系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值
该项目是一个基于Java语言开发的水果管理系统设计源码,包含53个文件,其中包括30个Java源文件、13个XML配置文件、6个JAR包文件、1个Git忽略文件、1个属性文件以及1个SQL脚本文件。此系统旨在用于期末答辩展示,展示了开发者对Java编程和系统设计的深入理解。
java回顾、知识整理、拾遗、面试_java-review
mysql主从复制用struts2,spring,hibernate框架,搭建在线考试系统。网站支持(1)老师创建题库,创建题目,查看题目对题目进行增删改,发布考试(选择考试难中易比例),批改学生试卷,查看学生成绩。(.zip
一个基于Go语言实现的搜索引擎项目资源
那些年,与你同分同位次的同学都去了哪里?全国各大学在四川2020-2024年各专业最低录取分数及录取位次数据,高考志愿必备参考数据
基于grpc开发的跨语言的交互系统,集成BCS,Brower
那些年,与你同分同位次的同学都去了哪里?全国各大学在四川2020-2024年各专业最低录取分数及录取位次数据,高考志愿必备参考数据
那些年,与你同分同位次的同学都去了哪里?全国各大学在四川2020-2024年各专业最低录取分数及录取位次数据,高考志愿必备参考数据
那些年,与你同分同位次的同学都去了哪里?全国各大学在四川2020-2024年各专业最低录取分数及录取位次数据,高考志愿必备参考数据
基于go语言,使用gocv和socket实现摄像头视频传输项
apache-seatunnel-web-1.0.2
内容概要:本篇文章主要介绍了如何在VMware虚拟化平台上搭建并配置QNX Neutrino实时操作系统的步骤方法。文章首先给出了获取必要的安装文件来源,然后逐步指导用户如何完成QNX在虚拟机中的安装过程以及相关网络参数配置,包括选择适当的网络模式来实现宿主机器与QNX虚拟机之间的通信,具体为设置NAT模式或者桥接模式下的网络参数,如指定静态或动态获取IP地址的方法。 适用人群:对嵌入式开发感兴趣的技术人士,尤其是需要在Linux环境下开展工作的程序员和系统工程师。 使用场景及目标:通过详细的操作指南帮助初学者快速掌握在Windows或Linux主机上利用虚拟机搭建QNX Real-Time Operating System开发环境的基础技能,能够实现在该环境中运行简单的C/C++应用程序。 其他说明:本文不仅适用于QNX初学者作为入门引导资料,也为经验丰富的开发者提供了有关于特定环境配置的重要参考。由于涉及到的具体细节比较多,读者最好边操作边对照文章内容进行练习。同时要注意保持最新版本的虚拟化平台客户端和服务端程序以确保兼容性和稳定性。
stm32中dma结合ad的使用
yolo系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值
低全球变暖潜能值 (GWP) 制冷剂.docx
那些年,与你同分同位次的同学都去了哪里?全国各大学在四川2020-2024年各专业最低录取分数及录取位次数据,高考志愿必备参考数据
ubuntu