Spring核心思想,IoC与DI详解(如果还不明白,放弃java吧)
yuyutoo 2024-10-12 01:24 2 浏览 0 评论
.IoC是什么?
IoC(Inversion of Control)控制反转,IoC是一种新的Java编程模式,目前很多轻量级容器都在广泛使用的模式。
2.IoC解决了什么问题?
在IoC出现以前,组件之间的协调关系是由程序内部代码来控制的,或者说,以前我们使用New关键字来实现两组间之间的依赖关系的。
这种方式就造成了组件之间的互相耦合。IoC(控制反转)就是来解决这个问题的,它将实现组件间的关系从程序内部提到外部容器来管理。
也就是说,由容器在运行期将组件间的某种依赖关系动态的注入组件中。
3.IoC的实现方式 及 与DI的关系?
(1).依赖查找(Dependency Lookup):容器中的受控对象通过容器的API来查找自己所依赖的资源和协作对象。
这种方式虽然降低了对象间的依赖,但是同时也使用到了容器的API,造成了我们无法在容器外使用和测试对象。
依赖查找是一种更加传统的IoC实现方式。
(2).依赖注入(Dependency Injection):这就是DI,字面上理解,依赖注入就是将服务注入到使用它的地方。对象只提供普通的方法让容器去决定依赖关系,
容器全权负责组件的装配,它会把符合依赖关系的对象通过属性(JavaBean中的setter)或者是构造子传递给需要的对象。
相对于IoC而言,依赖注入(DI)更加准确地描述了IoC的设计理念。所谓依赖注入,即组件之间的依赖关系由容器在应用系统运行期来决定,
也就是由容器动态地将某种依赖关系的目标对象实例注入到应用系统中的各个关联的组件之中。
4.Spring中的IoC与DI:
IoC是Spring的核心,贯穿始终。对于Spring框架来说,就是由Spring来负责控制对象的生命周期和对象间的关系。
Spring中DI有两种实现方式---Setter方式(传值方式)和构造器方式(引用方式)。
IoC与DI
首先想说说IoC(Inversion of Control,控制倒转)。这是spring的核心,贯穿始终。所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。这是什么意思呢,举个简单的例子,我们是如何找女朋友的?常见的情况是,我们到处去看哪里有长得漂亮身材又好的mm,然后打听她们的兴趣爱好、qq号、电话号、ip号、iq号………,想办法认识她们,投其所好送其所要,然后嘿嘿……这个过程是复杂深奥的,我们必须自己设计和面对每个环节。传统的程序开发也是如此,在一个对象中,如果要使用另外的对象,就必须得到它(自己new一个,或者从JNDI中查询一个),使用完之后还要将对象销毁(比如Connection等),对象始终会和其他的接口或类藕合起来。
那么IoC是如何做的呢?有点像通过婚介找女朋友,在我和女朋友之间引入了一个第三者:婚姻介绍所。婚介管理了很多男男女女的资料,我可以向婚介提出一个列表,告诉它我想找个什么样的女朋友,比如长得像李嘉欣,身材像林熙雷,唱歌像周杰伦,速度像卡洛斯,技术像齐达内之类的,然后婚介就会按照我们的要求,提供一个mm,我们只需要去和她谈恋爱、结婚就行了。简单明了,如果婚介给我们的人选不符合要求,我们就会抛出异常。整个过程不再由我自己控制,而是有婚介这样一个类似容器的机构来控制。Spring所倡导的开发方式就是如此,所有的类都会在spring容器中登记,告诉spring你是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。如果你还不明白的话,我决定放弃。
IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢? Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。关于反射的相关资料请查阅java doc。
理解了IoC和DI的概念后,一切都将变得简单明了,剩下的工作只是在spring的框架中堆积木而已。
如果还不明白,放弃java吧!
下面来让大家了解一下Spring到底是怎么运行的。
- public static void main(String[] args) {
- ApplicationContext context = new FileSystemXmlApplicationContext(
- "applicationContext.xml");
- Animal animal = (Animal) context.getBean("animal");
- animal.say();
- }
这段代码你一定很熟悉吧,不过还是让我们分析一下它吧,首先是applicationContext.xml
- <bean id="animal" class="phz.springframework.test.Cat">
- <property name="name" value="kitty" />
- </bean>
他有一个类phz.springframework.test.Cat
- public class Cat implements Animal {
- private String name;
- public void say() {
- System.out.println("I am " + name + "!");
- }
- public void setName(String name) {
- this.name = name;
- }
- }
实现了phz.springframework.test.Animal接口 itxxz.com
- public interface Animal {
- public void say();
- }
很明显上面的代码输出I am kitty!
那么到底Spring是如何做到的呢?
接下来就让我们自己写个Spring 来看看Spring 到底是怎么运行的吧!
首先,我们定义一个Bean类,这个类用来存放一个Bean拥有的属性
- /* Bean Id */
- private String id;
- /* Bean Class */
- private String type;
- /* Bean Property */
- private Map<String, Object> properties = new HashMap<String, Object>();
一个Bean包括id,type,和Properties。
接下来Spring 就开始加载我们的配置文件了,将我们配置的信息保存在一个HashMap中,HashMap的key就是Bean 的 Id ,HasMap 的value是这个Bean,只有这样我们才能通过context.getBean("animal")这个方法获得Animal这个类。我们都知道Spirng可以注入基本类型,而且可以注入像List,Map这样的类型,接下来就让我们以Map为例看看Spring是怎么保存的吧
Map配置可以像下面的
- <bean id="test" class="Test">
- <property name="testMap">
- <map>
- <entry key="a">
- <value>1</value>
- </entry>
- <entry key="b">
- <value>2</value>
- </entry>
- </map>
- </property>
- </bean>
Spring是怎样保存上面的配置呢?,代码如下:
- if (beanProperty.element("map") != null) {
- Map<String, Object> propertiesMap = new HashMap<String, Object>();
- Element propertiesListMap = (Element) beanProperty
- .elements().get(0);
- Iterator<?> propertiesIterator = propertiesListMap
- .elements().iterator();
- while (propertiesIterator.hasNext()) {
- Element vet = (Element) propertiesIterator.next();
- if (vet.getName().equals("entry")) {
- String key = vet.attributeValue("key");
- Iterator<?> valuesIterator = vet.elements()
- .iterator();
- while (valuesIterator.hasNext()) {
- Element value = (Element) valuesIterator.next();
- if (value.getName().equals("value")) {
- propertiesMap.put(key, value.getText());
- }
- if (value.getName().equals("ref")) {
- propertiesMap.put(key, new String[] { value
- .attributeValue("bean") });
- }
- }
- }
- }
- bean.getProperties().put(name, propertiesMap);
- }
IT学习者(www.itxxz.com)
接下来就进入最核心部分了,让我们看看Spring 到底是怎么依赖注入的吧,其实依赖注入的思想也很简单,它是通过反射机制实现的,在实例化一个类时,它通过反射调用类中set方法将事先保存在HashMap中的类属性注入到类中。让我们看看具体它是怎么做的吧。
首先实例化一个类,像这样
- public static Object newInstance(String className) {
- Class<?> cls = null;
- Object obj = null;
- try {
- cls = Class.forName(className);
- obj = cls.newInstance();
- } catch (ClassNotFoundException e) {
- throw new RuntimeException(e);
- } catch (InstantiationException e) {
- throw new RuntimeException(e);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- return obj;
- }
接着它将这个类的依赖注入进去,像这样
- public static void setProperty(Object obj, String name, String value) {
- Class<? extends Object> clazz = obj.getClass();
- try {
- String methodName = returnSetMthodName(name);
- Method[] ms = clazz.getMethods();
- for (Method m : ms) {
- if (m.getName().equals(methodName)) {
- if (m.getParameterTypes().length == 1) {
- Class<?> clazzParameterType = m.getParameterTypes()[0];
- setFieldValue(clazzParameterType.getName(), value, m,
- obj);
- break;
- }
- }
- }
- } catch (SecurityException e) {
- throw new RuntimeException(e);
- } catch (IllegalArgumentException e) {
- throw new RuntimeException(e);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- } catch (InvocationTargetException e) {
- throw new RuntimeException(e);
- }
- }
最后它将这个类的实例返回给我们,我们就可以用了。我们还是以Map为例看看它是怎么做的,我写的代码里面是创建一个HashMap并把该HashMap注入到需要注入的类中,像这样, itxxz.com
- if (value instanceof Map) {
- Iterator<?> entryIterator = ((Map<?, ?>) value).entrySet()
- .iterator();
- Map<String, Object> map = new HashMap<String, Object>();
- while (entryIterator.hasNext()) {
- Entry<?, ?> entryMap = (Entry<?, ?>) entryIterator.next();
- if (entryMap.getValue() instanceof String[]) {
- map.put((String) entryMap.getKey(),
- getBean(((String[]) entryMap.getValue())[0]));
- }
- }
- BeanProcesser.setProperty(obj, property, map);
- }
好了,这样我们就可以用Spring 给我们创建的类了,是不是也不是很难啊?当然Spring能做到的远不止这些,这个示例程序仅仅提供了Spring最核心的依赖注入功能中的一部分。
相关推荐
- 史上最全的浏览器兼容性问题和解决方案
-
微信ID:WEB_wysj(点击关注)◎◎◎◎◎◎◎◎◎一┳═┻︻▄(页底留言开放,欢迎来吐槽)●●●...
-
- 平面设计基础知识_平面设计基础知识实验收获与总结
-
CSS构造颜色,背景与图像1.使用span更好的控制文本中局部区域的文本:文本;2.使用display属性提供区块转变:display:inline(是内联的...
-
2025-02-21 16:01 yuyutoo
- 写作排版简单三步就行-工具篇_作文排版模板
-
和我们工作中日常word排版内部交流不同,这篇教程介绍的写作排版主要是用于“微信公众号、头条号”网络展示。写作展现的是我的思考,排版是让写作在网格上更好地展现。在写作上花费时间是有累积复利优势的,在排...
- 写一个2048的游戏_2048小游戏功能实现
-
1.创建HTML文件1.打开一个文本编辑器,例如Notepad++、SublimeText、VisualStudioCode等。2.将以下HTML代码复制并粘贴到文本编辑器中:html...
- 今天你穿“短袖”了吗?青岛最高23℃!接下来几天气温更刺激……
-
最近的天气暖和得让很多小伙伴们喊“热”!!! 昨天的气温到底升得有多高呢?你家有没有榜上有名?...
- CSS不规则卡片,纯CSS制作优惠券样式,CSS实现锯齿样式
-
之前也有写过CSS优惠券样式《CSS3径向渐变实现优惠券波浪造型》,这次再来温习一遍,并且将更为详细的讲解,从布局到具体样式说明,最后定义CSS变量,自定义主题颜色。布局...
- 你的自我界限够强大吗?_你的自我界限够强大吗英文
-
我的结果:A、该设立新的界限...
- 行内元素与块级元素,以及区别_行内元素和块级元素有什么区别?
-
行内元素与块级元素首先,CSS规范规定,每个元素都有display属性,确定该元素的类型,每个元素都有默认的display值,分别为块级(block)、行内(inline)。块级元素:(以下列举比较常...
-
- 让“成都速度”跑得潇潇洒洒,地上地下共享轨交繁华
-
去年的两会期间,习近平总书记在参加人大会议四川代表团审议时,对治蜀兴川提出了明确要求,指明了前行方向,并带来了“祝四川人民的生活越来越安逸”的美好祝福。又是一年...
-
2025-02-21 16:00 yuyutoo
- 今年国家综合性消防救援队伍计划招录消防员15000名
-
记者24日从应急管理部获悉,国家综合性消防救援队伍2023年消防员招录工作已正式启动。今年共计划招录消防员15000名,其中高校应届毕业生5000名、退役士兵5000名、社会青年5000名。本次招录的...
- 一起盘点最新 Chrome v133 的5大主流特性 ?
-
1.CSS的高级attr()方法CSSattr()函数是CSSLevel5中用于检索DOM元素的属性值并将其用于CSS属性值,类似于var()函数替换自定义属性值的方式。...
- 竞走团体世锦赛5月太仓举行 世界冠军杨家玉担任形象大使
-
style="text-align:center;"data-mce-style="text-align:...
- 学物理能做什么?_学物理能做什么 卢昌海
-
作者:曹则贤中国科学院物理研究所原标题:《物理学:ASourceofPowerforMan》在2006年中央电视台《对话》栏目的某期节目中,主持人问过我一个的问题:“学物理的人,如果日后不...
-
- 你不知道的关于这只眯眼兔的6个小秘密
-
在你们忙着给熊本君做表情包的时候,要知道,最先在网络上引起轰动的可是这只脸上只有两条缝的兔子——兔斯基。今年,它更是迎来了自己的10岁生日。①关于德艺双馨“老艺...
-
2025-02-21 16:00 yuyutoo
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- mybatis plus (70)
- scheduledtask (71)
- css滚动条 (60)
- java学生成绩管理系统 (59)
- 结构体数组 (69)
- databasemetadata (64)
- javastatic (68)
- jsp实用教程 (53)
- fontawesome (57)
- widget开发 (57)
- vb net教程 (62)
- hibernate 教程 (63)
- case语句 (57)
- svn连接 (74)
- directoryindex (69)
- session timeout (58)
- textbox换行 (67)
- extension_dir (64)
- linearlayout (58)
- vba高级教程 (75)
- iframe用法 (58)
- sqlparameter (59)
- trim函数 (59)
- flex布局 (63)
- contextloaderlistener (56)