`
BucketLi
  • 浏览: 189508 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
博客专栏
5a76a659-f8e6-3bf3-b39a-8ae8f7a0f9d9
Percolator与分布...
浏览量:5544
社区版块
存档分类
最新评论

Spring ioc容器简要分析

 
阅读更多
一直在用Spring容器,读书的时候也大概看过一些实现原理,不过比较模糊。趁元旦,花个几小时debug一把,看看简单的ioc流程并且tips把。

public class ApplicationContextTest {
    public static void main(String[] args){
    	ApplicationContext ctx=new ClassPathXmlApplicationContext("classpath:org/springframework/context/innertest/spring-context.xml");
    	CodeGeFactory factory=(CodeGeFactory) ctx.getBean("generatorFactory");
    	System.out.println(factory.getCodeGenerator().generate());
    }
}


<bean id="generatorFactory"     class="org.springframework.context.innertest.pojo.CodeGeFactory">
     <property name="codeGenerator" ref="codeGenerator"/>
</bean>

<bean id="codeGenerator" class="org.springframework.context.innertest.pojo.JavaCodeGenerator"/>



示例代码很简单,不细说,就是一个注入,然后定义顺序颠倒。这里首先区分下ApplicationContext和BeanFactory,前者包装在BeanFactory之上,主要做一些bean定义的解析以及各种processer和特殊bean(xxxAware实现类)的初始化以及调用,而真正的bean实例化以及ioc工作都在BeanFactory中做。

初始化工作主要在实例化ClassPathXmlApplicationContext的时候。首先对路径本身做了placeHolder的占位符(${xxx})替换,并且存储这些配置文件路径。随后进入主体初始化方法refresh()方法中。refresh()主要做的事情如下:

1. 初始化placeholder并校验properties,用于配置文件(或字符串)转换到BeanDefinition的替换.
2. 创建beanFactory,读取配置文件解析xml中的信息,主要包括bean的id,对应的class全名,以及依赖的bean的名称等信息,这个时候全是文本信息,不做初始化以及注入等工作。值得一提的是,spring根据location字符串的前缀将整个资源封装成不同类型的Resource,使用对应的ResourceLoader来加载,不过说到底,最后也是通过具体的classloder(通俗点来说就是不同的文件位置)加上相对文件路径找到文件资源罢了。Spring做了层层封装,可能是为了支持其看上去过度丰富的资源类型而不得已为之。
3. 中间做了一大堆的外部processer的实例化和invoke.示例没有定义,所以全部跳过了。
4. 通过反射实例化bean,然后查找依赖的bean,没初始化的直接初始化,这也解释了在bean的定义中先后关系并不重要,因为只要定义的xml(或者其他)已经被load进来并且封装成BeanDefinition,那么肯定能够被容器查找到并实例化起来。至于注入,中间代码有一大堆(属性编辑器),没有细究,最后是通过反射拿到相关属性的write method invoke一把就完成了注入(构造器注入以及注解注入步骤也差不多)。最终放入容器。
5.使用的时候(ctx.getBean("generatorFactory"))也就是拿到容器中缓存的实例。这里值得注意的一点是,默认的spring bean都是单例。


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics