Spring5基础(2)——Spring IoC控制反转(基础)

Spring IoC控制反转概念

csdn内容同步,id同名,csdn博客链接

Inversion of Control(IoC)控制反转:是一种通过描述(xml配置文件或注解),并通过第三方去产生或获取特定对象的方式。

实现控制反转的是:IoC容器。
操作方法是:依赖注入。
控制反转的结果是对象实例不再有调用者创建,而是由Spring容器来创建,即控制权由调用者转移到Spring容器。

Spring的依赖注入:Spring容器负责将被依赖的对象(需要的对象实例),赋值给调用者的成员变量,相当于为调用者注入了它所依赖的实例。

为什么要使用Spring IoC,作用是什么?

使用Spring IoC的作用是:消减程序间的耦合问题。

举个栗子:比如在B类中需要一个A类的实例对象,在B类中若使用New关键字来创建A类实例,按如下所示:

package com.lipiao.demo;

public class A {
    String name;
    public void setName(String name) {
        this.name = name;
    }
}
package com.lipiao.demo;

public class B {

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        //修改前
        A a=new A();
        a.setName("A1");
        System.out.println(a.name);
    }
}

运行效果就是控制台输出A1:


解耦前

实际开发中肯定不止2个类,随着逻辑处理越来越多,这样的处理方式会使不同的类之间耦合越来越严重,代码的维护会比较困难。

耦合:程序间的依赖关系
包括:①类之间的依赖 ②方法之间的依赖
弊端 独立性很差

解耦:尽可能降低程序间的依赖关系(经可能是因为有的耦合没法避免)
实际开发中应该做到:编译期间不依赖,运行时才依赖

解耦思路:
第一步:使用反射来创建对象,而避免使用new关键字
第二步:通过读取配置文件来获取要创建的对象权限定类名

使用java的反射特性来修改上面的B类中的代码,假设A类所在包路径为:com.lipiao.demo.A

package com.lipiao.demo;
public class B {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        //修改前
        A a=new A();
        a.setName("A1");
        System.out.println(a.name);
        
        //使用反射
        Class<?> classA = Class.forName("com.lipiao.demo.A");
        A a2=(A)classA.newInstance();
        a2.setName("A2");
        System.out.println(a2.name);
    }
}

运行效果如下:


使用java反射初步解耦

这样New关键字就没有啦,初步解耦就完成啦。

更多java反射特性的使用,本文不多撰写啦,我找了一片博客:Java的高级特性 - 反射

但是以上代码还没有做到编译期间不依赖,运行时才依赖

进一步解耦就要使用Spring IoC控制反转啦,通过依赖注入,让IoC容器帮我们创建实例对象。

Spring IoC容器的基本使用

实现控制反转的是:IoC容器。

Spring IoC容器的设计基于两个接口:
①BeanFactory接口,使用绝对路径

//3.使用Spring  IoC容器 BeanFactory接口 使用绝对路径
        BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource
                ("C:\\Users\\11092\\IdeaProjects\\javaEE\\src\\main\\resources\\META-INF\\applicationContext.xml"));
        //通过容器创建A类实例,xml中id为A,getBean传入A
        A a3 = (A) beanFactory.getBean("A");
        System.out.println(a3.name);

applicationContext.xml

<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="A" class="com.lipiao.demo.A">
        <property name="name" value="A3"></property>
    </bean>
</beans>
XmlBeanFactory

②ApplicationContext接口

1.使用ClassPathXmlApplicationContext创建ApplicationContext接口实例,使用相对路径(resources根目录)

//4.使用Spring  IoC容器 ApplicationContext接口
        //有3种创建ApplicationContext接口的方式:

        //4.1 ClassPathXmlApplicationContext 使用相对路径(resources根目录)
        ApplicationContext applicationContext4_1 =
                new ClassPathXmlApplicationContext("META-INF/applicationContext.xml");
        A a4_1= (A) applicationContext4_1.getBean("A4_1");
        System.out.println(a4_1.name);

applicationContext.xml

<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="A4_1" class="com.lipiao.demo.A">
        <property name="name" value="A4_1"></property>
    </bean>
</beans>

会有两条红色的提示信息,一条是刷新ClassPathXmlApplicationContext,一条是从xml配置文件中加载对应的bean文件
运行结果:控制台输出A4_1


ClassPathXmlApplicationContext

2.使用FileSystemXmlApplicationContext创建ApplicationContext接口实例,使用绝对路径

//4.2 FileSystemXmlApplicationContext 使用绝对路径
        ApplicationContext applicationContext4_2= new FileSystemXmlApplicationContext(
                "C:\\Users\\11092\\IdeaProjects\\javaEE\\src\\main\\resources\\META-INF\\applicationContext.xml");
        A a4_2= (A) applicationContext4_2.getBean("A4_2");
        System.out.println(a4_2.name);

applicationContext.xml

<bean id="A4_2" class="com.lipiao.demo.A">
        <property name="name" value="A4_2"></property>
    </bean>

会有两条红色的提示信息,一条是刷新ClassPathXmlApplicationContext,一条是从xml配置文件中加载对应的bean文件
运行结果:控制台输出A4_2

FileSystemXmlApplicationContext

3.使用web服务器实例化ApplicationContext容器
一般使用基于org.springframework.web.context.ContextLoaderListener的实现方式,在web.xml文件中添加:

<context-parm>
   <param-name>contextConfigLocation</param-name>
   <param-value>
      classpath:applicationContext.xml
   </param-value>
</context-parm>

<listener>
   <listener-class>
       org.springframework.web.context.ContextLoaderListener
   </listener-class>
</listener>

Spring IoC容器的依赖注入类型

①构造方法注入
Spring框架可以采用java的反射机制,通过构造方法完成依赖注入。
以下面这个C类为例:

package com.lipiao.demo;
//Spring  IoC容器依赖注入 1.构造方法注入
public class C {
    String name;
    public C(String name) {
        this.name = name;
    }
}

applicationContext.xml中

<bean id="C5_1" class="com.lipiao.demo.C">
        <constructor-arg index="0" value="C_strName_constructor"/>
    </bean>

index用于定义参数的位置,value表示参数为常数,若为实例引用,将value替换为ref
运行效果:
会有两条红色的提示信息,一条是刷新ClassPathXmlApplicationContext,一条是从xml配置文件中加载对应的bean文件
控制台打印C_strName_constructor

信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@7d907bac: startup date [Wed Jul 17 21:12:40 CST 2019]; root of context hierarchy
七月 17, 2019 9:12:40 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [META-INF/applicationContext.xml]
C_strName_constructor

②使用属性的setter方法注入(这是最主流的注入方式)
使用setter注入方法和构造方法注入类似,刚刚在介绍Spring IoC容器的基本使用的案例都是使用属性setter注入的。
还是看个例子吧,同样是上面的C类,修改C类代码,添加setter方法,删掉构造方法:

package com.lipiao.demo;
//Spring  IoC容器依赖注入 
// 1.构造方法注入
// 2.setter方法注入
public class C {
    String name;
    //构造方法注入
//    public C(String name) {
//        this.name = name;
//    }
    //setter方法注入
    public void setName(String name) {
        this.name = name;
    }
}

修改applicationContext.xml配置信息:

<bean id="C5_2" class="com.lipiao.demo.C">
        <property name="name" value="C_strName_setter"/>
    </bean>

运行效果:
会有两条红色的提示信息,一条是刷新ClassPathXmlApplicationContext,一条是从xml配置文件中加载对应的bean文件
控制台打印C_strName_setter

信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@148080bb: startup date [Wed Jul 17 21:29:37 CST 2019]; root of context hierarchy
七月 17, 2019 9:29:37 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [META-INF/applicationContext.xml]
C_strName_setter
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容