spring专题系列之IOC的理解和分析

根据时间安排,今天主要是对spring中IOC的理解。对于IOC的理解可以从以下几个角度去分析。

  • 什么是IOC?如何使用案例来理解?
  • IOC有哪几种实现方式?
  • IOC的底层实现过程是什么?

根据这几个角度,开始今天的故事,

1 什么是IOC?

对于IOC的理解,主要是停留在概念和几种注入的方式上,虽然知道其生命周期,但是对整个bean管理的宏观角度,理解的不够深刻。

IOC:控制反转(Inversion of Control)容器,是一种设计思想。意味着将你设计好的对象交给容器控制。

1.1 什么是依赖注入

这个概念的理解,我准备使用一个案例来表示。如果a类中包含了b类,就说明a类对b类产生了依赖。如一个人需要车,这就说人对车产生了依赖。

class User{ 
  Car car; 
  public User(){ 
    car=new Car(); 
  } 
}

上面这个案例,可以看到,在User类中,包含了Car类,也就说User类对Car类产生了依赖。

按照传统的方式,User类如果想要使用Car基本上就是在内部new一个新对象即可。但是这样做缺点很大,new的方式也就意味着User和Car产生了紧耦合。不利于大规模使用。于是使用了另外一种方式可以代替。那就是什么时候用到Car,从外部直接传递过来就好。这样的话,耦合性就大大降低了。再看下面这种形式是不是就好很多了。

class User{ 
  Car car; 
  public User(Car car){ 
    this.car=car; 
  } 
}

像这样的方式就是依赖注入,也就是把依赖Car注入到了User中。

1.2 什么是控制反转

有了上面依赖注入的概念,再立即控制反转就比较简单了。

  • 谁控制谁:传统方式User是在内部new,现在我们通过依赖注入的方式注入依赖对象Car。现在spring出现了,发明了IOC,IOC里面有一个容器,这些依赖对象全部交给容器去管理。也就是说这些依赖对象的控制权交给了容器。

  • 如何反转:传统方式User是主动去new,这种方式是正转。反转是由容器来帮忙创建及注入依赖对象;

2 依赖注入的几种形式

目前主要有五种注入方式:SET注入,构造器注入,静态工厂,实例工厂。

本文直接使用网上的基本案例来实现。比如UserService依赖UserDao。先把UserDao定义好了,接下来看如何实现注入的。

public class UserDao {
    public String userLogin() {
        return  "userLogin()方法";
    }
}

下面看几种依赖注入的几种实现方式。

2.1 set注入

第一步:XML配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="userDao" class="com.xxx.demo.UserDao"></bean>
    <!-- setter注入 -->
    <bean id="userService" class="com.xxx.demo.UserService">
        <!--ref是对于外部bean对象引用,与被引用的bean对象的id保持一致-->
        <property name="userDao" ref="userDao"></property>
    </bean>
</beans>

第二步:set方式注入

public class UserService {
    //一定要提供属性的setter方法
    private UserDao userDao;
    public void userlogin() {
        String res=userDao.userLogin();
        System.out.println(res);
    }
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}

这种方式简单易操作。

2.2 构造器注入

第一步:XML配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="userDao" class="com.xxx.demo.UserDao"></bean>
    <!-- 构造器注入 -->
    <bean id="userServiceV2" class="com.xxx.demo.UserServiceV2">
        <constructor-arg index="0" ref="userDao"></constructor-arg>
        <constructor-arg index="1" value="印度三哥"></constructor-arg>
    </bean>
</beans>

第二步:构造器注入

public class UserServiceV2 {
    private UserDao userDao;
    private String name;
    public void userlogin() {
        String res=userDao.userLogin();
        System.out.println(res);
        System.out.println(name);
    }
    public UserServiceV2(UserDao userDao,String name) {
        super();
        this.userDao = userDao;
        this.name = name;
    }
}

2.3 静态工厂注入

第一步:XML配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- 静态工厂注入 -->
    <bean id="userDao01" class="com.xxx.demo.StaticFactory" factory-method="createuserDao"></bean>
    <bean id="userService01" class="com.xxx.demo.UserService">
        <property name="userDao" ref="userDao01"></property>
    </bean>
</beans>

第二步:定义静态工厂

public class StaticFactory {
    public static UserDao createuserDao(){
        return new UserDao();
    }
}

第三部:静态工厂注入

public class UserService {
    private UserDao userDao;
    public void userlogin() {
        String res=userDao.userLogin();
        System.out.println(res);
    }
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}

2.4 实例化工厂

第一步:XML配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- 实例化工厂 -->
    <bean id="instanceFactory" class="com.xxx.demo.InstanceFactory"></bean>
    <bean id="userDao3" factory-bean="instanceFactory" factory-method="createUserDao"></bean>
    <bean id="userService02" class="com.xxx.demo.UserService">
        <property name="userDao" ref="userDao3"></property>
    </bean>
</beans>

第二步:工厂注入

public class InstanceFactory {
    public UserDao createUserDao(){
        return new UserDao();
    }
}

以上就是几种常见的注入方式。在开发中比较常用。知道了IOC的概念和几种实现方式之后,下面主要探讨IOC的底层实现原理。

3 IOC底层实现过程

以上的几种注入方式,可能有个疑问,那就是bean是如何从xml,再到注入类中的呢?看下面这张图

核心原理.png

Spring IOC容器初始化的核心过程主要有四个步骤(还有一些如:后置加载器,国际化,事件广播器等一些过程不展开):

  1. Bean定义的定位,Bean 可能定义在XML中,或者一个注解,或者其他形式。这些都被用Resource来定位,读取Resource获取BeanDefinition 注册到 Bean定义注册表中。
  2. 第一次向容器getBean操作会触发Bean的创建过程,实列化一个Bean时 ,根据BeanDefinition中类信息等实列化Bean。
  3. 将实列化的Bean放到单列Bean缓存内。
  4. 此后再次获取向容器getBean就会从缓存中获取。

这张图是核心的过程。这个过程是已经简化了,具体的实现方式要设计到bean的生命周期的管理。安排到下一章节了。
spring的核心内容就是aop和ioc,知道了这俩是如何实现的之后,就是核心bean管理的核心实现,最后对配置文件进行介绍。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容