zoukankan      html  css  js  c++  java
  • 面试真题--------spring源码解析IOC

    spring是我经常使用的框架,可是你真的对spring理解吗? 还是只知道它得使用。如果你想知道它真实的面目请仔细向下看。

    1.spring是如何知道哪些Bean需要实例化的?

        容器启动过程中,首先调用DispatcherSerlvet的init方法,init方法内部根据web.xml的配置,读取配置的上下文readspring-servlet.xml,然后逐句解析该上下文,当它读取到context:component-scan标签时,就启动对应的解析器,也可以叫做扫描器,对应的Class为:ComponentScanBeanDefinitionParser。这个类ComponentScanBeanDefinitionParser中调用了doScan方法,可以看到传了一个参数:basePackages,就是我们配置的路径。

    这样,就读取到了需要被实例化的所有类,之后这些类的信息会被封装成一个一个的BeanDefinition,然后保存到DefaultListableBeanFactory的beanDefinitionMap中供后续使用。

        /** Map of bean definition objects, keyed by bean name */
        private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();

    2.Spring中Bean是什么时候被实例化的?

      所有的这些Bean,在容器启动的时候,已经全部被实例化了。

    下面看代码一探究竟,还得看模板方法,AbstractApplicationContext.refresh(),其中有这么一个方法

      // Instantiate all remaining (non-lazy-init) singletons.
      finishBeanFactoryInitialization(beanFactory);

    看注释知道:实例化剩下的所有单例。

    Spring中的Bean默认都是单例的,除非显示的声明为prototype。

    剩下的(remaining)的意思是有一些Spring自身的处理器、解析器等Bean不是在这里实例化的,我们自己编写的常规类Controller、Service等全部都是在此处实例化。

    3.实例化的过程

       首先循环所有的BeanDefinition列表,然后调用getBean()方法,检查是否被实例化,如果没有被实例化则调用createBean()方法,具体的实例化是利用cglib类库,通过Java反射原理,构造函数实例化方式去实例化。然后组装Bean,把Bean属性设置进去,这里就是依赖注入了,把实例化好的serviceInstance注入到Service中。实例化成功后将实力保存到singletonObjects Map中。

    所有的Bean被实例化后,会被存入这个Map中供后续使用。

    DefaultSingletonBeanRegistry.java

        /** Cache of singleton objects: bean name --> bean instance */
        private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>();

    4.Bean的Scope

      (1)Singleton:一个Spring容器中只有一个Bean的实例,此为Spring的默认配置,全容器共享一个实例。

      (2)Prototype:每次调用新建一个Bean实例。

      (3)Request:Web项目中,给每一个 http request 新建一个Bean实例。

      (4)Session:Web项目中,给每一个 http session 新建一个Bean实例。

      (5)GlobalSession:这个只在portal应用中有用,给每一个 global http session 新建一个Bean实例。

    其中request,session和global session只适用于Web应用程序中,通常是与XmlWebApplicationContext一起使用,在实现上,singleton和prototype两种类型的容器的标准类型,而Scope request,session和global session是继承于自定义的Scope接口,如果用户有特殊的需要,可以继承这个接口并注册到容器中,即可使用用户自定义的Scope类型。用户自定义的Scope必须自己维护所管辖对象的初始化及销毁,即容器将这些对象的生存周期委托给Scope管理,而容器只管理Scope对象本身就可以。

    5. 注解怎么做到声明接口就可以将实现类注入?

    Spring主要利用了Class.isAssignableFrom()方法来实现接口与实现类的匹配。

      Class1.isAssignableFrom(Class2):如果Class1是Class2本身或者是其接口或者父类,则返回true,否则返回false;

    以testService的实例化为例,当Spring容器启动的时候,首先会读取配置文件,经过定位、加载、解析、注册,最终把标注了注解的类(例如:标注了@Service的TestServiceImpl)注册到BeanDefination的Map中并且缓存。

    然后,在实例化testService的时候,Spring此刻并不知道testService的实现类是哪个,而是循环遍历BeanDefinitionMap中的Bean,逐一与ITestService接口进行类型匹配,一旦匹配上就认定为其实现类,并对其进行实例化。



    参考----http://www.cnblogs.com/notDog/p/5420727.html

                https://www.cnblogs.com/dyppp/p/7397290.html

                https://www.imooc.com/article/19601

  • 相关阅读:
    第五章 Internet协议
    第四章 地址解析协议
    Learn the shell
    Linux学习前的准备
    第三章 链路层
    第二章 Internet 地址结构
    后台数据导出为Excel
    C#开发客户端、JAVA和tomcat开发服务端
    Java基础
    C++学习笔记--(1)
  • 原文地址:https://www.cnblogs.com/technologykai/p/9046168.html
Copyright © 2011-2022 走看看