查看: 1488|回复: 0

[Java语言] Spring IoC学习总结

发表于 2017-8-9 08:00:01
句号论坛
Spring IoC学习总结

学习spring Ioc整理的一些笔记,很简单。分享给大家。

IoC 基本概念

在这之前,我们先记住一句话。好莱坞原则:Don't call us, we will call you.
其实这句话很恰当地形容了“反转”的意味;
Ioc, Inversion of Control,控制反转,它还有一个别名叫“依赖注入”(DI Dependency Injection)。IoC不是什么技术,而是一种设计思想。在java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”

谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。 为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

还有一个概念:DI 依赖注入。大部分认为IoC和DI只是不同的叫法而已。
理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么

谁依赖于谁:当然是应用程序依赖于IoC容器; 为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源; 谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象; 注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。

Spring IoC

我理解的spring IoC分为两部分:Bean实例的创建依赖注入

Spring IoC容器如何实例化Bean呢?传统应用程序可以通过new和反射方式进行实例化Bean。而Spring IoC容器则需要根据Bean定义里的配置元数据使用反射机制来创建Bean。(大家可以了解一下Java的反射机制,这是Spring Ioc实现Bean实例化的核心机制)在Spring IoC容器中根据Bean定义创建Bean主要有以下几种方式:

使用构造器实例化Bean 有参/无参 使用静态工厂实例化Bean 使用实例工厂实例化Bean
  1. <!--使用默认构造参数-->
  2. <bean name="bean1" class="com.java.spring.Demo"/>
  3. <!--使用有参数构造参数-->
  4. <bean name="bean2" class="com.java.spring.Demo">
  5. <!-- 指定构造器参数 -->
  6. <constructor-arg index="0" value="Hello Spring!"/>
  7. </bean>
  8. <!-- 使用静态工厂方法 -->
  9. <bean id="bean3" class="com.java.spring.DemoStaticFactory" factory-method="newInstance">
  10. <constructor-arg index="0" value="Hello Spring!"/>
  11. </bean>
  12. <!--1、定义实例工厂Bean -->
  13. <bean id="DemoInstanceFactoryv"
  14. class="com.java.spring.DemoInstanceFactory"/>
  15. <!—2、使用实例工厂Bean创建Bean -->
  16. <bean id="bean4"
  17. factory-bean="DemoInstanceFactory"
  18. factory-method="newInstance">
  19. <constructor-arg index="0" value="Hello Spring!"></constructor-arg>
  20. </bean>
复制代码

另外,静态工厂和实例工厂方法还有对应的静态工厂类和实例工厂类

  1. /**
  2. * 静态工厂类
  3. *
  4. **/
  5. public class DemoStaticFactory {
  6. //工厂方法
  7. public static HelloApi newInstance(String message) {
  8. //返回需要的Bean实例
  9. return new Demo(message);
  10. }
  11. }
  12. /**
  13. * 实例工厂类
  14. *
  15. **/
  16. package com.java.spring;
  17. public class DemoInstanceFactory {
  18. public HelloApi newInstance(String message) {
  19. return new Demo(message);
  20. }
  21. }
复制代码

这一块补充一个细节。Spring什么时候实例化bean,首先要分2种情况:

第一:如果你使用BeanFactory作为Spring Bean的工厂类,则所有的bean都是在第一次使用该Bean的时候实例化

第二:如果你使用ApplicationContext作为Spring Bean的工厂类,则又分为以下几种情况:

  1. (1):如果bean的scope是singleton的,并且lazy-init为false(默认是false,所以可以不用设置),则ApplicationContext启动的时候就实例化该Bean,并且将实例化的Bean放在一个map结构的缓存中,下次再使用该Bean的时候,直接从这个缓存中取
  2. (2):如果bean的scope是singleton的,并且lazy-init为true,则该Bean的实例化是在第一次使用该Bean的时候进行实例化
  3. (3):如果bean的scope是prototype的,则该Bean的实例化是在第一次使用该Bean的时候进行实例化
复制代码

通常使用ApplicationContext作为容器的。

使用@Autowire注解注入的时机则是容器刚启动的时候就开始注入;注入之前要先初始化bean;
ApplicationContext 的初始化和BeanFactory 有一个重大的区别:BeanFactory在初始化容器时,并未实例化Bean,直到第一次访问某个Bean 时才实例目标Bean;而ApplicationContext 则在初始化应用上下文时就实例化所有单实例的Bean。


了解Bean的实例化后,接下来就是Bean实例之间的关系,也就是依赖注入;
Spring IoC容器的依赖有两层含义:Bean依赖容器容器注入Bean的依赖资源

Bean依赖容器:也就是说Bean要依赖于容器,这里的依赖是指容器负责创建Bean并管理Bean的生命周期,正是由于由容器来控制创建Bean并注入依赖,也就是控制权被反转了,这也正是IoC名字的由来,此处的有依赖是指Bean和容器之间的依赖关系。 容器注入Bean的依赖资源:容器负责注入Bean的依赖资源,依赖资源可以是Bean、外部文件、常量数据等,在Java中都反映为对象,并且由容器负责组装Bean之间的依赖关系,此处的依赖是指Bean之间的依赖关系,可以认为是传统类与类之间的“关联”、“聚合”、“组合”关系。

Spring IoC容器注入依赖资源主要有以下两种基本实现方式:

构造器注入:就是容器实例化Bean时注入那些依赖,通过在在Bean定义中指定构造器参数进行注入依赖,包括实例工厂方法参数注入依赖,但静态工厂方法参数不允许注入依赖; setter注入:通过setter方法进行注入依赖;

一、构造器注入:
1)常量值

  1. <constructor-arg index="0" value="常量"/> <!--简写 -->
  2. <constructor-arg index="0"><value>常量</value></constructor-arg><!--全写 -->
复制代码

2)引用

  1. <constructor-arg index="0" ref="引用"/><!--简写 -->
  2. <constructor-arg index="0"><ref bean="引用"/></constructor-arg><!--全写 -->
复制代码

二、setter注入:
1)常量值

  1. <property name="message" value="常量"/><!--简写 -->
  2. <property name="message"><value>常量</value></ property><!--全写 -->
复制代码

2)引用

  1. <property name="message" ref="引用"/><!--简写 -->
  2. <property name="message"><ref bean="引用"/></ property><!--全写 -->
复制代码

3)数组:

  1. <property name="values">
  2. <array>
  3. <value>1</value>
  4. <value>2</value>
  5. <value>3</value>
  6. </array>
  7. </property>
复制代码

4)列表:

  1. <property name="values">
  2. <list>
  3. <value>1</value>
  4. <value>2</value>
  5. <value>3</value>
  6. </list>
  7. </property>
复制代码

5)集合:

  1. <property name="values">
  2. <set>
  3. <value>1</value>
  4. <value>2</value>
  5. <value>3</value>
  6. </set>
  7. </property>
复制代码

6)字典

  1. <!--简写 -->
  2. <map>
  3. <entry key="键常量" value="值常量"/>
  4. <entry key-ref="键引用" value-ref="值引用"/>
  5. </map>
  6. <!--全写 -->
  7. <map>
  8. <entry><key><value>键常量</value></key><value>值常量</value></entry>
  9. <entry><key><ref bean="键引用"/></key><ref bean="值引用"/></entry>
  10. </map>
复制代码

7)Properties

另外,基于注解驱动的Spring Ioc的原理以及Spring IoC源码剖析相关我在在网上找到一些文章,大家也可以看一下。
Spring依赖注入的两种方式
使用注释驱动的Ioc功能
Spring IoC源码剖析



太阳http代理AD
回复

使用道具 举报

关闭

站长推荐上一条 /1 下一条