Spring IOC 学习笔记

版权声明:本文为博主原创文章,转载请注明作者与出处,http://blog.csdn.net/lixingtao0520 https://blog.csdn.net/lixingtao0520/article/details/83833401

1、IoC思想 .

如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:

●谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。

●为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。 

理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:

●谁依赖于谁:当然是应用程序依赖于IoC容器;

●为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;

●谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;

●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)

2、Spring初始化IoC容器的过程。

Spring 先加载beanDefinition到beanFactory中(用map存储,key是beanName),beanDefinition是bean数据结构的一种映射。然后处理beanDefiniton(怎么处理?)。完成bean注册beanFactory中。在完成之前,先预实例化那些单例bean(lazy-init为false的)。

3、IoC容器的初始化包括BeanDefinition的Resource定位,载入和注册。

(1)、定位:使用BeanDefinitionReader读取资源applicationContext.xml文件。

(2)、载入:读取xml文件中定义的Bean,然后表示成IoC容器内部的数据结构beanDefinition,包括xml中定义的和component_scan自动扫描到的带有@service,@controller,@dao注解的bean。

疑问?spring是用哪个类解析xml中定义的component_scan路径并scan所有bean的?

(3)、注册:向IoC容器注册这些BeanDefinition的过程。通过调用BeanDefinitionRegistry接口的实现来完成的,这个注册是把载入过程解析到的BeanDefinition向IoC容器进行注册。在IoC内部是通过一个HashMap来保存这些BeanDefinition数据的

4、IoC容器的初始化不包含Bean依赖注入的实现,一般依赖注入发生在应用第一次向容器通过getBean索取Bean时。但可以根据BeanDefinition信息中的Lazyinit属性来设定。即为false时,在容器初始化完成后,就预实例化。

    预实例化时,先从父类容器中判断是否有缓存,父类没有从子类容器判断是否有缓存。

public void preInstantiateSingletons() throws BeansException {
          if (this.logger.isInfoEnabled()) {
              this.logger.info("Pre-instantiating singletons in " + this);
          }
          synchronized (this.beanDefinitionMap) {
              // Iterate over a copy to allow for init methods which in turn register new bean definitions.
              // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
              List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
              for (String beanName : beanNames) {
                   RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);//父类中获取。
                   if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                        if (isFactoryBean(beanName)) {
                             final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
                             boolean isEagerInit;
                             if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                                  isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                                      public Boolean run() {
                                           return ((SmartFactoryBean<?>) factory).isEagerInit();
                                      }
                                  }, getAccessControlContext());
                             }
                             else {
                                  isEagerInit = (factory instanceof SmartFactoryBean &&
                                           ((SmartFactoryBean<?>) factory).isEagerInit());
                             }
                             if (isEagerInit) {
                                  getBean(beanName);
                             }
                        }
                        else {
                             getBean(beanName);
                        }
                   }
              }
          }
     }

5、Spring IoC对于不同scope的对象是怎么管理的?

    如果是single模式,那么直接取容器中的实例,那如果是原型模式,是每次getBean的时候,创建新实例吗?//TODO

6、为什么用Spring IoC而不是用工厂模式?

     使用工厂模式时,调用者仍然需要定位到工厂,使调用者和工厂耦合到一起。需要调用被调用者时直接IoC依赖注入。

7、几种注入的不同@Resource,@Autowired,@Qualier?

TODO

8、IOC的注入方式?

参见这里》Spring常用的三种注入方式  构造函数注入,Setter注入,基于注解的注入

参考:

Spring:源码解读Spring IOC原理

浅谈对Spring IOC以及DI的理解

猜你喜欢

转载自blog.csdn.net/lixingtao0520/article/details/83833401