毕业刚刚一年多一点,毕业了后也顺利的进入了一家著名的互联网公司,做的是后台系统,用的呢也是SSI(struts2,spring)框架,平时做做项目,也已足够了,但是感觉越来越没动力了,越来越没有激情了,就像我们的老大说的,"天天接Task,有意思?,有时间不知道把框架的源码看看!",最近加班相对较少,闲下来就来摸索一下spring。

写这篇文章只是想让大家了解一下Spring到底是怎么运行的,并不是想重造噢,希望大家看完这篇文章后能对Spring有更深入的了解,对初学者有所帮助喔!好,言归正传,让我们来一起探索吧!

我们先开看看spring是怎么运行的。。

  //读取配置文件实例化一个IoC容器
ApplicationContext ctx=new ClassPathXmlApplicationContext("resources/beans.xml");
//从容器中获取Bean,注意此处完全“面向接口编程,而不是面向实现”
PersonService personService=(PersonService) ctx.getBean("personService",PersonService.class);
personService.sayHello();

我们来分析一下,首先是加载spring的配置文件,此处是beans.xml

     <bean id="personService" class="com.yangyang.service.impl.PersonServiceImpl">
</bean>

然后是通过调用getBean方法来获取并实例化personService对象,最后是调用sayHello方法

那么spring到底是如何做到的呢?很明显,第一步肯定是要解析bean.xml文件,

为此我们写一个自己的ClassPathXmlApplicationContext类来模拟spring的行为,,此处加入一个参数为string类型的构造函数,用来读取配置文件及模拟spring以后的行为,

 package com.juit;

 public class YhdClassPathXmlApplicationContext {
/**
* 构造方法,用来模拟spring的行为
* @param fileName
*/
public YhdClassPathXmlApplicationContext(String fileName){
this.readXml(fileName);
}
/**
* 根据文件名读取xml的配置文件
* @param fileName
* Administer
* 2013-8-26 下午11:09:16
*/
private void readXml(String fileName) {
// TODO Auto-generated method stub }
}

此处readxml啥都没做,现在我们来完成这个代码,根据http://www.cnblogs.com/shunyang/p/3265100.html中提到的方式来解析xml文件,并将解析到的bean存到一个bean定义的类中,为此我们需要准备一个类BeanDefinition 用来存储解析后xml文件。经过分析xml文件,可知比较简单的配置一般有id,class(当然这里为了简单只用了两个)等属性,如下:

当然我们也需要加上一个全局的List的bean,用来存储所有的beans,代码见后面

 package com.juit;
/**
* Bean对象
* @author Administer
*
*/
public class BeanDefinition {
private String id;//bean的id
private String className;//bean的类
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public BeanDefinition(String id, String className) {
this.id = id;
this.className = className;
}
}

下面是解析xml文件的readXml方法:

 private void readXml(String fileName) {
//创建一个读取器
SAXReader saxReader=new SAXReader();
Document document=null;
try {
//获取要读取的配置文件的路径
URL xmlPath=this.getClass().getClassLoader().getResource(fileName);
//读取文件内容
document=saxReader.read(xmlPath);
//获取xml中的根元素
Element rootElement=document.getRootElement();
for (Iterator iterator = rootElement.elementIterator(); iterator.hasNext();) {
Element element = (Element) iterator.next();
String id=element.attributeValue("id");//获取bean的id属性值
String clazz=element.attributeValue("class");//获取bean的class属性值
BeanDefinition beanDefinition=new BeanDefinition(id,clazz);
beanDefines.add(beanDefinition);
}
} catch (Exception e) {
e.printStackTrace();
}
}

解析完xml后,接下来就是bean的实例化,我们在写一个实例化bean的方法。

spring中是使用getBean的方式来获取bean的,类似的可以用Map的get取值来模拟,因此定义一个Map,用来存储bean的id和bean的对应,完整的见下面

 
 public class YhdClassPathXmlApplicationContext{
private List<BeanDefinition> beanDefines=new ArrayList<BeanDefinition>();//用来存储所有的beans
private Map<String, Object> sigletons =new HashMap<String, Object>();//用来存储实例化后的bean
/**
* 构造方法,用来模拟spring的行为
* @param fileName
*/
public YhdClassPathXmlApplicationContext1(String fileName){
//1.读取spring的配置文件
this.readXml(fileName);
//2.实例化bean
this.instanceBeans();
}
/**
* 完成实例化beans
*
* Administer
* 2013-8-26 下午11:24:37
*/
private void instanceBeans() {
// TODO Auto-generated method stub }


然后我们来完成instanceBeans方法

 /**
* 完成实例化beans
*
* Administer
* 2013-8-18 上午1:07:51
*/
private void instanceBeans() {
if (beanDefines != null && beanDefines.size() >0) {
//对每个bean进行实例化
for (BeanDefinition beanDefinition : beanDefines) {
try {
//bean的class属性存在的时候才进行实例化,否则不进行实例化
if (beanDefinition.getClassName() != null && !beanDefinition.getClassName().equals("")) {
//实例化的关键操作
sigletons.put(beanDefinition.getId(),Class.forName(beanDefinition.getClassName()).newInstance());
System.out.println("id为:"+beanDefinition.getId()+"的bean实例化成功");
}
} catch (Exception e) {
System.out.println("bean实例化失败");
e.printStackTrace();
}
}
}
}

实例化后我们来写一个getBean方法,用来在外部获取实例化后的bean,这个搞个最简单的根据bean的id来获取

 /**
* 通过bean名称来获取bean对象
* @param beanName
* @return
* Administer
* 2013-8-18 上午1:17:02
*/
public Object getBean(String beanName){
return sigletons.get(beanName);
}

这样整个bean的实例化我们已经做完了,是不是也不是很困难,当然我们还缺少一步,我们需要测试我们这个自己写的这个spring是不是OK的,

 package com.juit;

 import org.junit.BeforeClass;
import org.junit.Test; import com.juit.YhdClassPathXmlApplicationContext;
import com.yangyang.service.PersonService; public class SpringTest { @BeforeClass
public static void setUpBeforeClass() throws Exception {
} @Test
public void testInstanceSping() {
YhdClassPathXmlApplicationContext ctx=new YhdClassPathXmlApplicationContext("resources/beans.xml");
PersonService personService=(PersonService)ctx.getBean("personService"); } }

可以看到控制台打印着"

id为:personService的bean实例化成功

终于大功告成了,当然这些只是我这个菜鸟的理解,欢迎各位大神的指导,接下来下篇将会实现spring的依赖注入。

自己动手写spring容器(1)的更多相关文章

  1. 自己动手写spring容器(3)

    好久没有写博客了,今天闲下来将之前未完成的表达出来. 在之前的文章自己动手写spring容器(2)中完成了对spring的依赖注入的实现,这篇将会介绍spring基于注解的依赖注入的实现. 在一般的J ...

  2. 自己动手写spring容器(2)

    上篇我们自己写了一个很简单的spring容器,该容器只是做了简单的bean的实例化,并没有spring的核心之一的IOC(依赖注入),也叫做控制反转,这里我就不讲这个的具体含义,不知道的园友可以自行百 ...

  3. 自己动手写Spring框架--IOC、MVC

    对于一名Java开发人员,我相信没有人不知道 Spring 框架,而且也能够轻松就说出 Spring 的特性-- IOC.MVC.AOP.ORM(batis). 下面我想简单介绍一下我写的轻量级的 S ...

  4. 自己动手编写spring IOC源码

    前言:对于spring IOC概念不是很了解的朋友可以阅读我上一篇博客--轻松理解spring IOC(这两篇博客也是由于我的个人原因导致现在才发布,惭愧啊).通过这篇博客的理解之后,相信大家会对sp ...

  5. [原]容器学习(一):动手模拟spring的IoC

    介绍 学习经典框架的实现原理以及设计模式在其实际中的运用,是非常有必要的,可以让我们更好进行面向对象. 本篇文章就来模拟Spring的IOC功能,明白原理后,可以更好的使用它,进而为进行面向对象提供一 ...

  6. 容器学习(一):动手模拟spring的IoC

    介绍 学习经典框架的实现原理以及设计模式在事实上际中的运用,是很有必要的,能够让我们更好进行面向对象. 本篇文章就来模拟Spring的IOC功能.明确原理后,能够更好的使用它,进而为进行面向对象提供一 ...

  7. 我自横刀向天笑,手写Spring IOC容器,快来Look Look!

    目录 IOC分析 IOC是什么 IOC能够带来什么好处 IOC容器是做什么工作的 IOC容器是否是工厂模式的实例 IOC设计实现 设计IOC需要什么 定义接口 一:Bean工厂接口 二:Bean定义的 ...

  8. 手写Spring,定义标记类型Aware接口,实现感知容器对象

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 同事写的代码,我竟丝毫看不懂! 大佬的代码,就像 "赖蛤蟆泡青蛙,张的丑玩 ...

  9. 自己动手开发IOC容器

    前两天写简历.写了一句:精通Spring IoC容器.怎么个精通法?还是自己动手写个IOC容器吧. 什么是IoC(Inversion of Control)?什么是DI(Dependency Inje ...

随机推荐

  1. .net EF 事物 订单流水号的生成 (二):观察者模式、事物、EF

    针对.net EF 事物 订单流水号的生成 (一)  的封装. 数据依然不变. using System; using System.Linq; using System.Transactions; ...

  2. github basic usage in windows

    1. create a new accout, create orginazation, create repo 2. install git in your local pc Note: you c ...

  3. Mongodb操作之查询(循序渐进对比SQL语句)

    工具推荐:Robomongo,可自行百度寻找下载源,个人比较推荐这个工具,相比较mongoVUE则更加灵活. 集合简单查询方法 mongodb语法:db.collection.find()  //co ...

  4. MVC+Jqgrid

    基于MVC+Jqgrid的列表页面 2014-12-08 12:01 by 刘尼玛, 1583 阅读, 20 评论, 收藏, 编辑 一.前言 “尼玛哥,上周你教我改了下OA系统UI,黄总看了很满意呀. ...

  5. Asp.net Identity 系列之 怎样修改Microsoft.AspNet.Identity.EntityFramework.IdentityUser 的 Id 字段的数据类型

    这篇博客我们来学习如何将AspNetUsers 表的Id 字段 的类型由nvarchar(128) 改为Int 并且子增长 1.为什么要修改 如果你运行过 Asp.net mvc 示例项目,你好会发现 ...

  6. 使用JSmooth制造java jar文件可以运行exe文件教程图像

    这是我之前在个人博客3yj上面写的一篇文章,如今转载过来,原文地址 (这不是广告哦) 几年前,刚接触java的是.就想用一些方法把自己的劳动果实保护起来,曾经也用过非常多这种工具.有一个特别好用,今天 ...

  7. 曲演杂坛--一条DELETE引发的思考

    原文:曲演杂坛--一条DELETE引发的思考 场景介绍: 我们有一张表,专门用来生成自增ID供业务使用,表结构如下: CREATE TABLE TB001 ( ID ,) PRIMARY KEY, D ...

  8. 解决:错误的语法:”XXXX“必须是批处理中仅有的语句

    原文:解决:错误的语法:”XXXX“必须是批处理中仅有的语句   SQL Server 数据库提示“错误的语法:”XXXX“必须是批处理中仅有的语句”报错的原因分析 解析:批处理必须以 CREATE ...

  9. javascript图片延迟加载(转载)

    <!DOCTYPE HTML><html><head><meta http-equiv="Content-Type" content=&q ...

  10. 【工作笔记二】ASP.NET MVC框架下使用MVVM模式

    ASP.NET MVC框架下使用MVVM模式 原文:http://www.cnblogs.com/n-pei/archive/2011/07/21/2113022.html 对于asp.net mvc ...