- 浏览: 84818 次
- 性别:
- 来自: 杭州
最新评论
-
xvshell:
写的通俗易懂
Spring温故知新(九)Spring自动代理 (系列第一部分完结篇) -
雅礼彭培:
写的好,理解了
Spring温故知新(九)Spring自动代理 (系列第一部分完结篇) -
gongjinglin1989:
大神,能指教1,2吗?我想请教几个问题,我们现在有做好得web ...
Hybrid App的实际运用项目 -
bolide74:
jacking124 写道恭喜你呀!!3Q
新年展望 -
bolide74:
zlex 写道不要泄密呀轩?我有hold住啊,没算泄密吧……
新年展望
在介绍Spring的IoC容器之前,我首先要给大家介绍一下我刚刚花了仅仅10分钟就写出来的一个用HashMap而不是用XML来配置的IoC容器,然后剖析这段代码,彻底的撕碎初学者对于IoC概念的恐惧感(好像有点夸张了,哈哈!)
首先还是亲切的Robot类:
为了解释,这个类只有一个属性。使用了set注入
这里我把类名叫做RobotBean,这是为了提前让大家知道Bean这么一个东西,告诉大家这个就是一个Bean,而关于Bean到底代表着什么意思,那么下回我就会介绍了。
下面就是简易IoC容器的代码了:
然后是实现类的应用代码:
这时候大家可以用这一段实现类代码和最初的第一篇HelloWorld的代码比较一下,是不是特别神似?http://bolide74.iteye.com/blog/993248只不过Spring的HelloWorld在实例化ApplicationContext这个IoC容器的时候还需要传入一个XML配置文件的路径,而我这里直接省略了。
这是为什么呢?那是因为我没有用XML来配置IoC容器,而是直接在IoC容器里建了一个HashMap来当作配置文件,一样能起到简单的配置功能。
这个HashMap结构很简单,Key就是RobotBean的ID,它可以是任意的字符串,不需要跟RobotBean的类名相关;而Value就是RobotBean的完整类名了,包含了RobotBean的包名和类名,这个就不能乱写了哈!
当然以后如果你又做了一个PeopleBean想要把它也加进这个IoC容器里来管理,那也是同理,新建一个HashMap配置容器
那么接下来就是要介绍IoC容器的真正核心所在了,如何根据这个“配置容器”来获取到一个实例:getBean()!
其实要是清楚JAVA的反射机制的同学,不用我介绍就直接明白了,但是如果不清楚什么叫反射的同学,我这里用最通俗但是可以不太准确的说法来介绍:反射,就是根据一个类的完整类名(包名+类名),来把这个类实例化。注意,实例化出来的类型是一个类,叫做Class类类型。也就是是说Robot机器人不再是一个称呼,一个代号,而是切切实实存在的看的见摸的着一个种类(要还是不能理解,你就暂时把它想像成机器人工厂类的一个实例吧...)。
然后获取到了这么一个实例类以后,就可以直接调用一个newInstance()方法,也就是让这个实例类自动的产生一个这个类的实例对象给我们,就像是机器人工厂实例生产出了一个机器人。
这时候我们可以看到,getBean这个方法的返回类型是Object,也就是一个超类型。java也好C#也好都有一个特性,就是所有的类都是Object的子类,所以Object可以代表任何类。
这样一来的话,在应用代码中调用getBean()方法的时候,只要把返回类型强制转换为调用getBean方法的引用对象的类型就可以了。
以上内容,就基本上剖析了IoC的实现原理,当然真正Spring的IoC框架功能更强大,我这个在依赖注入的时候还是直接写死的类型,其实还可以自动判断的。但对于描述IoC容器实现原理没太大意义,这里就省略了。
最后我要告诉大家的是,以上内容纯属猜测,如有雷同那真是太巧啦!
我其实没看过Spring的源码哈,都是猜的,我想应该八九不离十,万一错了,千万别回头来找我算账,概不负责哦~
下一篇:Spring温故知新(五)Spring的Bean和IoC 容器 http://bolide74.iteye.com/blog/1004086
上一篇:Spring温故知新(三)singleton单例模式 http://bolide74.iteye.com/blog/1001630
嗯,会有这个疑问,可能是由于你还对Spring的依赖注入还不够了解。事实上如果你从第二章开始看起的话你就会发现,"在客户端测试类中获得bean实例后用户自己设置的"是msg这个值,也就是Speak方法的形参。
而name值是RobotBean类的一个成员属性,而不是方法的形参,因此是需要在获取RobotBean的实例之前就要在配置文件中注入,这样才能达到控制和管理实例的作用。
可以参照与前面几章的简单工厂方法来加强理解含义,如果不事先注入这个成员属性,那所谓的简单工厂方法也就没有了它存在的意义,而IoC的最大优势也就体现不出来了。
所以事实上,"我们在xml里只配置了bean的id和class,并没有把bean中属性的值也配进去"这个理解是错误的,xml里配置bean的id和class只是基础作用,更大的作用就是为了注入bean的属性
是的,不过我的初衷只为了解释原理而不是写一个成熟的IoC容器,因此尽可能的把与主题无关的代码给省略掉了,希望那些准备写自己的成熟容器的同学别学这个示例啊!
其实咱做编程的一向都是会的不难,难的就是不会,只要明白了原理以后就都很简单了
哈哈,看LZ很牛逼,看了几篇文章,嗯,非常不错,记得你说你学java是直接从spring开始扣得,我很佩服,我本来是搞java的后来干了半年,现在外包,干的乱七八糟,想复习无处下手,索性看看你得文章,很不错,像做了至少3年的人写的。得多学习啊
其实也是因为我有C#的基础,要不然也啃不下来啊
哈哈,看LZ很牛逼,看了几篇文章,嗯,非常不错,记得你说你学java是直接从spring开始扣得,我很佩服,我本来是搞java的后来干了半年,现在外包,干的乱七八糟,想复习无处下手,索性看看你得文章,很不错,像做了至少3年的人写的。得多学习啊
引用
以下示例只为了解释原理而不是写一个成熟的IoC容器,因此尽可能的把与主题无关的代码给省略掉了,希望那些准备写自己的成熟容器的同学别学这个示例
首先还是亲切的Robot类:
package com.iteye.bolide74.action; public class RobotBean { public String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public void Speak(String msg) { System.out.println(msg + ",我是" + this.name); } }
为了解释,这个类只有一个属性。使用了set注入
这里我把类名叫做RobotBean,这是为了提前让大家知道Bean这么一个东西,告诉大家这个就是一个Bean,而关于Bean到底代表着什么意思,那么下回我就会介绍了。
下面就是简易IoC容器的代码了:
package com.iteye.bolide74.action; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; public class MySpringIoC { public HashMap<String, HashMap<String, Object>> configLikeXML = new HashMap<String, HashMap<String, Object>>(); public MySpringIoC() { HashMap<String, Object> robotBeanConfig = new HashMap<String, Object>(); robotBeanConfig.put("class", "com.iteye.bolide74.action.RobotBean"); robotBeanConfig.put("name", "Robot1"); configLikeXML.put("Robot", robotBeanConfig); } public Object getBean(String beanID) { // 获取hashMap配置内容 HashMap<String, Object> beanConfig = this.configLikeXML.get(beanID); // 获取完整类名 String className = (String) beanConfig.get("class"); Class<?> bean = null; try { // 获取类类型实例 bean = Class.forName(className); } catch (ClassNotFoundException e1) { e1.printStackTrace(); } Object instance = null; try { // 获取这个类的一个实例 instance = bean.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } for (Field field : bean.getDeclaredFields()) { // 获取属性名 String fieldName = field.getName(); // 在hashMap获取属性要注入的值(这里为了方便把类型写死了) String fieldValue = (String) beanConfig.get(fieldName); Method method = null; try { // 获取到这个属性的set方法(这里为了方便把类型写死了) method = bean.getDeclaredMethod( "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1), new Class[] { String.class }); } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } try { // 调用set方法 method.invoke(instance, new Object[] { fieldValue }); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } return instance; } }
然后是实现类的应用代码:
package com.iteye.bolide74.tester; import com.iteye.bolide74.action.MySpringIoC; import com.iteye.bolide74.action.RobotBean; public class MySpringIoCTester { public static void main(String[] args) { MySpringIoC beanFactory = new MySpringIoC(); RobotBean robotBean = (RobotBean) beanFactory.getBean("Robot"); robotBean.Speak("Hello,world!"); } }
这时候大家可以用这一段实现类代码和最初的第一篇HelloWorld的代码比较一下,是不是特别神似?http://bolide74.iteye.com/blog/993248只不过Spring的HelloWorld在实例化ApplicationContext这个IoC容器的时候还需要传入一个XML配置文件的路径,而我这里直接省略了。
这是为什么呢?那是因为我没有用XML来配置IoC容器,而是直接在IoC容器里建了一个HashMap来当作配置文件,一样能起到简单的配置功能。
这个HashMap结构很简单,Key就是RobotBean的ID,它可以是任意的字符串,不需要跟RobotBean的类名相关;而Value就是RobotBean的完整类名了,包含了RobotBean的包名和类名,这个就不能乱写了哈!
当然以后如果你又做了一个PeopleBean想要把它也加进这个IoC容器里来管理,那也是同理,新建一个HashMap配置容器
那么接下来就是要介绍IoC容器的真正核心所在了,如何根据这个“配置容器”来获取到一个实例:getBean()!
其实要是清楚JAVA的反射机制的同学,不用我介绍就直接明白了,但是如果不清楚什么叫反射的同学,我这里用最通俗但是可以不太准确的说法来介绍:反射,就是根据一个类的完整类名(包名+类名),来把这个类实例化。注意,实例化出来的类型是一个类,叫做Class类类型。也就是是说Robot机器人不再是一个称呼,一个代号,而是切切实实存在的看的见摸的着一个种类(要还是不能理解,你就暂时把它想像成机器人工厂类的一个实例吧...)。
然后获取到了这么一个实例类以后,就可以直接调用一个newInstance()方法,也就是让这个实例类自动的产生一个这个类的实例对象给我们,就像是机器人工厂实例生产出了一个机器人。
这时候我们可以看到,getBean这个方法的返回类型是Object,也就是一个超类型。java也好C#也好都有一个特性,就是所有的类都是Object的子类,所以Object可以代表任何类。
这样一来的话,在应用代码中调用getBean()方法的时候,只要把返回类型强制转换为调用getBean方法的引用对象的类型就可以了。
以上内容,就基本上剖析了IoC的实现原理,当然真正Spring的IoC框架功能更强大,我这个在依赖注入的时候还是直接写死的类型,其实还可以自动判断的。但对于描述IoC容器实现原理没太大意义,这里就省略了。
最后我要告诉大家的是,以上内容纯属猜测,如有雷同那真是太巧啦!
我其实没看过Spring的源码哈,都是猜的,我想应该八九不离十,万一错了,千万别回头来找我算账,概不负责哦~
下一篇:Spring温故知新(五)Spring的Bean和IoC 容器 http://bolide74.iteye.com/blog/1004086
上一篇:Spring温故知新(三)singleton单例模式 http://bolide74.iteye.com/blog/1001630
评论
10 楼
bolide74
2011-05-10
yuanyu5237 写道
楼主,不好意思,我有点不明白,为什么要在robotBeanConfig.put("name", "Robot1"); 这里传入RobotBean的name值,我们在xml里只配置了bean的id和class,并没有把bean中属性的值也配进去,属性值(name的值)应该是再客户端测试类中获得了bean的实例后,用户自己设置的吧,希望楼主能解释下,谢谢
写的很不错,加你关注了
写的很不错,加你关注了
嗯,会有这个疑问,可能是由于你还对Spring的依赖注入还不够了解。事实上如果你从第二章开始看起的话你就会发现,"在客户端测试类中获得bean实例后用户自己设置的"是msg这个值,也就是Speak方法的形参。
而name值是RobotBean类的一个成员属性,而不是方法的形参,因此是需要在获取RobotBean的实例之前就要在配置文件中注入,这样才能达到控制和管理实例的作用。
可以参照与前面几章的简单工厂方法来加强理解含义,如果不事先注入这个成员属性,那所谓的简单工厂方法也就没有了它存在的意义,而IoC的最大优势也就体现不出来了。
所以事实上,"我们在xml里只配置了bean的id和class,并没有把bean中属性的值也配进去"这个理解是错误的,xml里配置bean的id和class只是基础作用,更大的作用就是为了注入bean的属性
9 楼
yuanyu5237
2011-05-10
楼主,不好意思,我有点不明白,为什么要在robotBeanConfig.put("name", "Robot1"); 这里传入RobotBean的name值,我们在xml里只配置了bean的id和class,并没有把bean中属性的值也配进去,属性值(name的值)应该是再客户端测试类中获得了bean的实例后,用户自己设置的吧,希望楼主能解释下,谢谢
写的很不错,加你关注了
写的很不错,加你关注了
8 楼
2xusi
2011-05-05
挺 好 的
7 楼
bolide74
2011-04-29
C.T 写道
你的Map容器如果是这样处理的话,应该至少加多一个方法,可以将你的映射放入你的
里面的robotBeanConfig中吧。这样方便点。
HashMap<String, Object> robotBeanConfig = new HashMap<String, Object>();
里面的robotBeanConfig中吧。这样方便点。
是的,不过我的初衷只为了解释原理而不是写一个成熟的IoC容器,因此尽可能的把与主题无关的代码给省略掉了,希望那些准备写自己的成熟容器的同学别学这个示例啊!
6 楼
C.T
2011-04-29
你的Map容器如果是这样处理的话,应该至少加多一个方法,可以将你的映射放入你的
里面的robotBeanConfig中吧。这样方便点。
HashMap<String, Object> robotBeanConfig = new HashMap<String, Object>();
里面的robotBeanConfig中吧。这样方便点。
5 楼
bolide74
2011-04-28
爪哇岛岛主 写道
无非就是一个填值的问题,我大二的时候写了一个很垃圾的,不过现在都无所谓写了,很多框架做的非常出色。。。
其实咱做编程的一向都是会的不难,难的就是不会,只要明白了原理以后就都很简单了
4 楼
bolide74
2011-04-28
竹隐江南 写道
bolide74 写道
消灭0回复! 莫非现在都只对单纯的设计模式感兴趣么。。。
哈哈,看LZ很牛逼,看了几篇文章,嗯,非常不错,记得你说你学java是直接从spring开始扣得,我很佩服,我本来是搞java的后来干了半年,现在外包,干的乱七八糟,想复习无处下手,索性看看你得文章,很不错,像做了至少3年的人写的。得多学习啊
其实也是因为我有C#的基础,要不然也啃不下来啊
3 楼
爪哇岛岛主
2011-04-28
无非就是一个填值的问题,我大二的时候写了一个很垃圾的,不过现在都无所谓写了,很多框架做的非常出色。。。
package util; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import pojo.Admin; public class FillPojo<T> { static Admin admin = null; @SuppressWarnings("unchecked") public T fillPojo(Class<T> obj,Map<String,Object> mapData) throws Exception{ Map.Entry<String, Object> param = null; Iterator<Map.Entry<String, Object>> it = mapData.entrySet().iterator(); T pojo = null; Class<?> myClass = null; String propertyName = null; Object propertyValue = null; Field field = null; Method method = null; StringBuffer methodName = null; myClass = Class.forName(obj.getName()); /** * 获取POJO实例 */ pojo = (T) myClass.newInstance(); while(it.hasNext()){ param = (Entry<String, Object>)it.next(); /** * 获取属性的名称和值 */ propertyName = param.getKey(); propertyValue = param.getValue(); /** * 获取属性的setter方法名称 */ methodName = new StringBuffer(); methodName.append("set"); methodName.append(propertyName.substring(0, 1).toUpperCase()); methodName.append(propertyName.substring(1)); field = myClass.getDeclaredField(propertyName); method = myClass.getMethod(methodName.toString(),field.getType()); method.invoke(pojo,propertyValue); } return pojo; } }
2 楼
竹隐江南
2011-04-28
bolide74 写道
消灭0回复! 莫非现在都只对单纯的设计模式感兴趣么。。。
哈哈,看LZ很牛逼,看了几篇文章,嗯,非常不错,记得你说你学java是直接从spring开始扣得,我很佩服,我本来是搞java的后来干了半年,现在外包,干的乱七八糟,想复习无处下手,索性看看你得文章,很不错,像做了至少3年的人写的。得多学习啊
1 楼
bolide74
2011-04-14
消灭0回复! 莫非现在都只对单纯的设计模式感兴趣么。。。
发表评论
-
Spring温故知新:WEB篇(二)Hello,World!
2011-08-29 15:22 3642在准备写代码之前,我们首先得把下列必备的库导入项目: spri ... -
Spring温故知新:WEB篇(一) 准备工作
2011-08-16 12:42 1597最近一直都忙着做项目还有一些私人的事情,都没时间更新,今天抽空 ... -
《Spring温故知新》第一部分<Spring基础> 电子书制作完毕,提供下载
2011-05-19 14:03 1936由于有人需要,所以刚刚把之前的Spring基础部分制作成了电子 ... -
Spring温故知新(九)Spring自动代理 (系列第一部分完结篇)
2011-05-19 10:29 3448这是《Spring温故知新》系列的第一部基础部分的最后一篇,简 ... -
Spring温故知新(八)静态切入点和CGLIB代理,更智能、更方便!
2011-05-18 10:17 2702前面一章我们利用了Spring的AOP框架实现了WALL-E自 ... -
Spring温故知新(七)Advice通知的5种类型
2011-05-10 12:52 5721这一章内容比较简单,就是大致的了解一下Spring的AOP框架 ... -
Spring温故知新(六)AOP面向切面编程 <3>
2011-05-09 13:19 2385我们开发小组跟网易的合作项目终于上线了,我自己的一些私人琐事也 ... -
Spring温故知新(六)AOP面向切面编程 <2>
2011-04-19 11:47 2609上一章我们讲到了用代 ... -
Spring温故知新(六)AOP面向切面编程 <1>
2011-04-18 16:55 2886这一章我们将开始剖析Spring框架最为重要的AOP(Aspe ... -
AbstractFactory 抽象工厂模式(已补完)
2011-04-13 16:54 3328为了跟别人的有所区别,我这里直接就用接口来实现抽象工厂了,毕竟 ... -
Spring温故知新(三)singleton单例模式
2011-04-13 14:29 7078本来今天打算介绍一下Spring的IoC容器,但是开了一早上的 ... -
Spring温故知新(二) IoC控制反转与DI依赖注入(修正1)
2011-04-12 11:20 6329学习Spring,所有教程都是从IoC和DI开始的,但 ... -
Spring温故知新(一)Hello,World!
2011-04-08 18:13 3120这是我的JAVA学习笔记的第一篇,由于本身就不是写给外人看的, ...
相关推荐
这部分可能会介绍如何创建第一个Spring应用,包括引入Spring库,创建bean定义,以及如何启动和使用Spring容器。 综合来看,这份"spring_2021.7.14.zip"压缩包提供了Spring框架的初级到中级的学习资源,涵盖了从基础...
在Spring AOP中,我们可以创建一个`SpeakerProxy`代理类,它实现了`ISpeaker`接口,并持有真实对象的引用。在代理类的`say()`方法中,我们可以在调用真实对象的`say()`方法前后添加`getGift()`和`giveGift()`。 ```...
"Spring全家桶"这一术语,指的是Spring生态系统中的一系列相互关联的项目和技术,它们共同构成了一个全面的企业级应用开发解决方案。本思维导图包含了Spring的主要组成部分,对于初学者而言,它是一个了解Spring框架...
尚硅谷_SpringCloud_Rest微服务案例-部门服务消费者.avi》这个视频中,可能详细讲解了一个具体的部门服务消费者案例,涵盖了如何使用Restful API与服务提供者进行交互,以及如何利用SpringCloud的组件来实现微服务间...
spring cloud + openshift example
Spring Cloud Config 是一个用于分布式系统配置管理的框架,它允许开发者在远程服务器上集中管理和版本化应用的配置,而不是在每个应用本地存储配置。这种方式在微服务架构中尤其有用,因为多个独立的服务需要共享和...
常用的spring注解大全,适合新手学习、老手温故知新。读懂spring,平步青云。
第二部分深入解读基于Docker的主流容器云技术,讲解了构建自己的容器云的方法,深入分析了3类Docker容器云技术的实现方法的设计思路,包括专注Docker容器编排与部署的容器云(Compose、Machine、Swarm、Fleet)、...
Spring的核心组件包括IoC容器、AOP、MVC等,用于简化企业级应用开发。 18. **什么是Maven?** Maven是一个项目管理和综合工具,它通过配置文件管理项目的构建、依赖关系和文档生成。 19. **Eclipse和IntelliJ ...
本课件集合旨在提供一个简单易懂的学习路径,适合初学者和有一定基础的开发者温故知新。 首先,Java的核心概念包括类、对象、封装、继承和多态。这些是理解Java编程的基础。类是对象的模板,它定义了一组特性和行为...
在`FilterDemo`这个例子中,我们可以创建一个自定义的Filter,配置在web.xml中,指定其拦截的URL模式。Filter可以通过`chain.doFilter(request, response)`来将请求传递给下一个Filter或目标资源。 ### 应用场景 -...
ASP.NET 2.0是微软开发的一个用于构建Web应用程序的框架,它基于.NET Framework,提供了丰富的功能和强大的性能。C#是一种面向对象的编程语言,是ASP.NET开发的主要语言之一,以其简洁、类型安全和高性能著称。在这...
### 自己动手写Struts:构建基于MVC的Web开发框架 #### 第一篇:Web框架入门 ##### 第1章 运筹帷幄:Web框架的核心思想 - **MVC模式** - **MVC模式概述**:MVC(Model-View-Controller)是一种常用的设计模式,...
初中语文文学讨论现当代文学温故知新
在本项目"温故知新,通过学习尚学堂飞机游戏项目,理解Java语言基础知识.zip"中,我们可以深入探讨Java编程语言的基础知识,并结合实际的游戏开发经验来加深理解。这是一个非常适合初学者或者想要巩固Java基础的...
考生应专注于理解和掌握每一个知识点,而不是一味追求学习的广度。要做到这一点,需要深入阅读课本,对每个概念都有精准的理解,不留下任何模糊不清的地方。同时,通过反复练习来熟悉和熟练掌握这些知识点,确保在...
《中信建设温故知新,从 4G 看 5G》这份资料主要探讨了移动通信技术从第四代(4G)到第五代(5G)的演进过程,以及这一演变带来的技术创新和产业影响。4G 和 5G 作为两个重要的通信时代,它们之间的差异和联系构成了...
中信建设温故知新,从 4G 看 5G.pdf