作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可。

上一章当中我没有提及具体的搭建环境的步骤,一个是不得不承认有点懒,另外一个我觉得如果上章所述的那些环境都还不会搭建的话,研究spring的源码还有些过早。

如果你有兴趣的话,相信已经搭建好了学习研究的环境,接下来就可以进入正题了。

网上也有很多关于spring源码学习的文章以及帖子,讲的也都不错,但是有些可能高估了读者的能力,该深入的地方反倒一句带过,我现在也是在一步一步研究,和大家的进度一样,所以可能在我的角度来和各位探讨,更加容易。

首先我们来说一下IOC,IOC是spring最核心的理念,包括AOP也要屈居第二,那么IOC到底是什么呢,四个字,控制反转。

网上有不少是这么解释IOC的,说IOC是将对象的创建和依赖关系交给容器,这句话我相信不少人都知道,在我个人的理解,IOC就是让我们的开发变的更简单了。

为什么这么说呢,光说没意思,直接上代码。

 public class Person {

    public void work(){
System.out.println("I am working");
}
}

上面这个是Person类,如果我们还有一个Company公司类,公司要开张需要人来工作,所以我们可能需要这样。

public class Company {

    public Person person;

    public Company(Person person){
this.person = person;
} public void open(){
person.work();
System.out.println("I am opening");
}
}

好了,这样可以了,虽说和现实有些区别,毕竟没有一个人的公司,但是就是这么个意思。必须要有人在公司里,公司才能开张。

有了spring上述情况我们是怎么写的呢?Person类不变,Company就可以简单些了。

public class Company {

    @Autowired
public Person person; public void open(){
person.work();
System.out.println("I am opening");
}
}

OK了,使用注解后,spring里的写法是这样的,是不是简单很多?或许你可能会说,这才减少了多少代码,但是事实上是,真正的项目中,不可能有这么简单的依赖关系,或许是2层,3层甚至N层。

当然,可能我们有时候用的XML,XML和注解的区别就在于这里,注解可以快速的完成依赖的注入,但是缺点也很明显,那就是比如我公司里不需要人了,我需要的是机器,那么我还要手动改代码,将Person换成机器(这里应该是英文,英语不好,懒得查了,只记得念“磨洗”),而如果是XML配置,那么我们只需要改下配置文件就可以。维护起来会方便很多,当然XML的缺点也很明显,那就是依赖关系复杂的时候,XML文件会比较臃肿,所以我们一般的做法是将XML分离开来。

说到这里,有些扯远了,但是我觉得以上可以足够说明IOC的好处,知道了IOC的好处,我们自然就要知道怎么来实现IOC了。

或许看了spring的源码,第一感觉是很蒙,包太多,我也很蒙,但是研究东西就是得沉下心来,先来关注一下这个接口,BeanFactory,附上代码。

package org.springframework.beans.factory;

import org.springframework.beans.BeansException;

/*
* @author Rod Johnson
* @author Juergen Hoeller
* @since 13 April 2001
*/
public interface BeanFactory { String FACTORY_BEAN_PREFIX = "&"; Object getBean(String name) throws BeansException; <T> T getBean(String name, Class<T> requiredType) throws BeansException; <T> T getBean(Class<T> requiredType) throws BeansException; Object getBean(String name, Object... args) throws BeansException; boolean containsBean(String name); boolean isSingleton(String name) throws NoSuchBeanDefinitionException; boolean isPrototype(String name) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException; Class<?> getType(String name) throws NoSuchBeanDefinitionException; String[] getAliases(String name); }

这个便是spring核心的Bean工厂定义,上面的author说是2001年写的,已经历史久远了,这个类是spring中所有bean工厂,也就是俗称的IOC容器的祖宗,各种IOC容器都只是它的实现或者为了满足特别需求的扩展实现,包括我们平时用的最多的ApplicationContext。从上面的方法就可以看出,这些工厂的实现最大的作用就是根据bean的名称亦或类型等等,来返回一个bean的实例。

一个工厂如果想拥有这样的功能,那么它一定需要以下几个因素:

1.需要持有各种bean的定义,否则无法正确的完成bean的实例化。

2.需要持有bean之间的依赖关系,否则在bean实例化的过程中也会出现问题。例如上例,如果我们只是各自持有Person和Company,却不知道他们的依赖关系,那么在Company初始化以后,调用open方法时,就会报空指针。这是因为Company其实并没有真正的被正确初始化。

3.以上两种都要依赖于我们所写的依赖关系的定义,暂且认为是XML文件(其实可以是各种各样的),那么我们需要一个工具来完成XML文件的读取。

我目前想到的,只需要满足以上三种条件,便可以创建一个bean工厂,来生产各种bean。当然,spring有更高级的做法,以上只是我们直观的去想如何实现IOC。

其实在上述过程中仍旧有一些问题,比如第一步,我们需要持有bean的定义,如何持有?这是一个问题。我们知道spring的XML配置文件中,有一个属性是lazy-init,这就说明,bean在何时实例化我们是可以控制的。这个属性默认是false,但是我们可以将这个属性设置为true,也就是说spring容器初始化以后,配置了延迟加载的各种bean都还未产生,它们只在需要的时候出现。

所以我们无法直接的创建一个Map<String,Object>来持有这些bean的实例,在这里要注意,我们要储存的是bean的定义,而非实例。

那么接下来,又是一个祖宗级别的接口要出现了,来看BeanDefinition。

package org.springframework.beans.factory.config;

import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.core.AttributeAccessor; public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement { String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON; String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE; int ROLE_APPLICATION = 0; int ROLE_SUPPORT = 1; int ROLE_INFRASTRUCTURE = 2; String getParentName(); void setParentName(String parentName); String getBeanClassName(); void setBeanClassName(String beanClassName); String getFactoryBeanName(); void setFactoryBeanName(String factoryBeanName); String getFactoryMethodName(); void setFactoryMethodName(String factoryMethodName); String getScope(); void setScope(String scope); boolean isLazyInit(); void setLazyInit(boolean lazyInit); String[] getDependsOn(); void setDependsOn(String[] dependsOn); boolean isAutowireCandidate(); void setAutowireCandidate(boolean autowireCandidate); boolean isPrimary(); void setPrimary(boolean primary); ConstructorArgumentValues getConstructorArgumentValues(); MutablePropertyValues getPropertyValues(); boolean isSingleton(); boolean isPrototype(); boolean isAbstract(); int getRole(); String getDescription(); String getResourceDescription(); BeanDefinition getOriginatingBeanDefinition(); }

顾名思义,这个便是spring中的bean定义接口,所以其实我们工厂里持有的bean定义,就是一堆这个玩意,或者是他的实现类和子接口。这个接口并非直接的祖宗接口,他所继承的两个接口一个是core下面的AttributeAccessor,继承这个接口就以为这我们的bean定义接口同样具有处理属性的能力,而另外一个是beans下面的BeanMetadataElement,字面翻译这个接口就是bean的元数据元素,它可以获得bean的配置定义的一个元素。在XML文件中来说,就是会持有一个bean标签。

仔细观看,能发现beanDefinition中有两个方法分别是String[] getDependsOn()和void setDependsOn(String[] dependsOn),这两个方法就是获取依赖的beanName和设置依赖的beanName,这样就好办了,只要我们有一个BeanDefinition,就可以完全的产生一个完整的bean实例。

今天就先到这里吧,我也是边看边写的,与其说跟我一起学,其实这个系列的应该叫源码学习笔记,更多的还是看到哪里,写到哪里,谈不上跟我一起学。

如果文中有不周到的地方,希望各位尽管指出。

spring源码学习之路---IOC初探(二)的更多相关文章

  1. spring源码学习之路---AOP初探(六)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 最近工作很忙,但当初打算学习 ...

  2. spring源码学习之路---IOC实现原理(三)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 上一章我们已经初步认识了Be ...

  3. spring源码学习之路---IOC容器初始化要义之bean定义载入(五)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 最近工作很忙,时间不多,研究 ...

  4. spring源码学习之路---深入AOP(终)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 上一章和各位一起看了一下sp ...

  5. spring源码学习之路---环境搭建(一)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 最近已经开始了spring源 ...

  6. [spring源码学习]一、IOC简介

    一.程序实例 假设一个简单地实例,我们有一个人,人可能有姓名,年龄等属性,每天上下班的时候需要坐车,他可能做小轿车,suv等,这样一个场景.我们很容易想到如下代码: 1.人的对象类,包括两个属性,姓名 ...

  7. [spring源码学习]十、IOC源码-conversionService

    一.代码示例 1.我们在之前的Person类里新增一个两个属性,分别是客户的兴趣和生日,兴趣爱好有很多,我们使用list进行保存,生日使用日期进行保存 public class Person { pr ...

  8. [spring源码学习]九、IOC源码-applicationEventMulticaster事件广播

    一.代码实例 回到第IOC的第七章context部分,我们看源码分析部分,可以看到在spring的bean加载之后的第二个重要的bean为applicationEventMulticaster,从字面 ...

  9. [spring源码学习]七、IOC源码-Context

    一.代码实例 如之前介绍的,spring中ioc是它最为核心的模块,前边花了大量时间分析spring的bean工厂和他如何生成bean,可是在我们实际应用中,很少直接使用beanFactory,因为s ...

随机推荐

  1. 【131031】html:hidden的使用

    一般来说,我们在使用Struts时,如果要在JSP隐式的传值给Action有两种情况: 1.要传的值是FromBean中的一个字段,你说的情况应该就是这种情况,例如需要在Edit页面中保存theID, ...

  2. oracle删除用户下所有的表

    需要创建这些删除语句,通过oracle的数据字典找到该用户下的所有表.视图等对象,拼接成语句.如下select 'drop table '||table_name|| ' cascade constr ...

  3. nexus私有仓库搭建

    步骤: 下载安装JDK(注意可用版本) .查看CentOS自带JDK是否已安装,输入: yum list installed |grep java 一般来说,如果是新装CentOS系统的话,不会有JD ...

  4. Uncaught ReferenceError: console is not defined

    今天写javascript代码遇到了这个极其神奇的问题,居然报错说内置的console不存在,而且后来我换成了alert也不行.照例说这些都是js代码内置的东西不应该出现这种错误.不过百度之发现貌似没 ...

  5. 深入理解ASP.NET 5的依赖注入

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:ASP.NET 5整个底层都架构于依赖注入机制之下,今天介绍的文章详细介绍了内置依赖注 ...

  6. 【使用Unity开发Windows Phone上的2D游戏】(1)千里之行始于足下

    写在前面的 其实这个名字起得不太欠当,Unity本身是很强大的工具,可以部署到很多个平台,而不仅仅是可以开发Windows Phone上的游戏. 只不过本人是Windows Phone 应用开发出身, ...

  7. Linux文本比较-diff&awk

    最近为了完成工作,需要将两个文件A.old和A进行比较,然后将A中新增加的部分保存到A中,其他部分删除.经过查找相关资料,发现有两种比较好的方法. 1. 使用diff命令 diff old.file ...

  8. input实时监控和获取焦点的问题,oninput,ononfocus

    1.input监控实时输入问题,google浏览器使用oninput,其他浏览器(IE6/7/8)使用onpropertychange var ie = !!window.ActiveXObject; ...

  9. Oracle注入漏洞

    sqlmap.py -u "http://10.7.82.123:9104/servlet/json" --cookie="JSESSIONID=abcgk26KDf_5 ...

  10. Loadrunner中百分比模式和Vuser模式

    从百分比模式切换到Vuser模式后,多个脚本时候,每个脚本的比例仍然维持不变: 切换到Vuser模式后: 如果在场景执行过程中需要动态添加Vuser,只能在Vuser模式下执行场景 如果需要执行“组” ...