首页 > 编程语言 > 详细

【Spring框架学习】IOC/DI机制

时间:2020-04-24 15:23:14      阅读:74      评论:0      收藏:0      [点我收藏+]

技术分享图片

基本概念:

  • IOC:
    Inversion of control
    控制反转
  • DI:
    dependence injection
    依赖注入

以上两个词是一个意思,只是站在不同的角度去描述同一件事情

那么,为什么说 是“依赖注入、控制反转”呢?
之前是程序员 主动维护 对象的创建
现在程序员把对象创建的权力交给了spring框架
spring框架 拥有了 对象创建的权力
程序员 失去了 对象创建的权力
对象创建的权力发生了反转,因此就被称为控制反转

通俗一点地讲:

因为 我们设置的对象,不是由我们去创建,去new,
而是通过Spring的IoC/DI机制,进行自动注入
因此,我们称之为“依赖注入
而 现在控制对象创建工作的,不是程序员而是程序
因此,我们称之为“控制反转


那么,为什么程序员 不new,而要让容器 进行 对象的注入呢?
答曰:
程序员主动去new,会导致如下几个缺点:

  • 扩展性差
  • 维护性差
  • 每一层的依赖严重
    servlet层 依赖 对象的创建
    service层 依赖 dao对象的创建

例如:
钱在你的口袋,钱的控制权在自己(相当于 new),
钱在银行,钱的控制权在银行(相当于 控制反转)
那么,当我们需要进行 转账、利息 等功能操作时,
就不用 来回跑、找办法 涨利息了


那么,现在本人就来讲解下IoC/DI机制的语法

IoC/DI机制的使用:

基本步骤:

  1. Maven添加相关依赖
  2. resources包下,创建名为applicationContext.xml核心配置文件
  3. 书写 配置文件的内容
  4. 在需要的类中通过ApplicationContext接口的实现类的getBean()方法
    配置文件中的id索引,获取指定的对象

那么,接下来,本人就来具体说明下每一步的细节吧:

具体说明:

首先,我们需要在Maven添加如下依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.1.9.RELEASE</version>
</dependency>

其次,我们需要在resources包下,
创建名为applicationContext.xml核心配置文件

本人现在来对这个配置文件做下说明
说明

spring的核心配置文件
也是spring容器配置文件
在此文件中目前主要配置Javabean
配置Javabean就是将 Javabean 交给 spring容器 进行管理

配置文件 书写格式

基本骨架

<bean id="" class="">
</bean>

那么,本人对上述的两个属性做下解释

解释

  • id
    是spring容器中bean的唯一标识
    程序中可以通过id 获取bean对象
  • class
    填写属性的值必须是类的全路径,以便底层反射机制的执行
    此刻的类必须严格遵守Javabean的规范,也就是需要有一个无参数构造方法

我们可以在上述格式中增加子级标签属性,来完善配置文件


那么,我们向配置文件中存储了数据,该如何读取呢?
答曰:

可以通过ApplicationContext接口的实现类的getBean()方法
配置文件中的id索引,获取指定的对象

现在,本人来展示下如何通过配置文件来获取指定的对象:
例子
本人先来给出一个之后要被注入的 SimpleClass类

package edu.youzg.about_Spring.core;

public class SimpleClass {

    public SimpleClass() {
    }

    public void doSomething() {
        System.out.println("Hello spring framework!");
    }

}

接下来,本人根据这个类的信息,来给出配置文件的信息:

<?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="simpleClass" class="edu.youzg.about_Spring.core.SimpleClass" />
</beans>

现在,本人来给出一个测试类

package edu.youzg.about_Spring.core;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Demo {
    
    public static void main(String[] args){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        SimpleClass simpleClass = context.getBean("simpleClass", SimpleClass.class);
        simpleClass.doSomething();
    }
    
}

那么,现在,本人来展示下运行结果:
技术分享图片
可以看到:我们并没有去new对象,却能够调用该类的非静态方法,
这就表明,我们通过配置文件,对对象的注入工作,成功了!


原理:

其实 spring容器方法是 由Beanfactory接口提供了最基础的spring容器方法。
上述的使用过程中,能看到我们使用了ApplicationContext接口的实现类,
实现了对象的注入工作

这是因为,ApplicationContext接口Beanfactory接口子接口
技术分享图片


那么,现在,本人来对上述的语法进行下解释:

配置文件式 语法:

spring框架提供的进行注入操作Java接口只有一个 —— ApplicationContext接口

那么,这个接口,有四个实现类


首先是 applicationContext.xml核心配置文件):

配置文件:

  1. 若要被注入的对象,创建方法无参构造:
    容器初始化的时候,spring容器默认会创建Java bean对象,
    底层实现是 通过反射机制调用类的 无参构造方法
<bean id="该对象的id" class="指定的类" scope="作用域">
</bean>

那么,本人对上文中的作用域做下说明:

作用域 取值

  • singleton:默认值,所注入的对象都是单例的(即:同一个对象)
  • proptotype:原型模式(相当于new),每次都是新的对象
  • request
  • session
  • application
  • websocket

例如:

<bean id="simpleClass" class="edu.youzg.about_Spring.core.SimpleClass" scope="singleton">
</bean>
  1. 若要被注入的对象,创建方法静态工厂类的某个方法
    这种注入方式用的不是很多,
    存在的意义是如果我们使用第三方提供的类私有构造方法使得类在外部不能访问没办法修改他人的代码
    就只能通过他人提供的静态工厂方法来创建:
<bean id="该对象的id" class="指定的类" factory-method="静态工厂所提供的类的创建方法">
</bean>

例如:

<!--将jdk 中 java.lang.Runtime类交给spring容器-->
<!--私有构造方法保证了类在外部不能访问,注意spring中为了编写代码的方便,破坏了java的封装性,可以在类的外部访问私有属性-->
<!--通过工厂方法创建对象的方式,用的不是很多,存在的意义是如果我们使用第三方提供的类,没办法修改他人的代码-->
<bean id="runtime" class="java.lang.Runtime" factory-method="getRuntime" />
  1. 若要被注入的对象,实例方法创建,
    一个工厂类提供一个工厂方法
<!--spring创建javabean的第三种方式使用实例方法创建-->
<bean id="工厂类的id" class="edu.youzg.about_spring.core.UserFactory" />

<!--指定工厂类userFactory,指定工厂方法getUS-->
<bean id="目标对象的id" factory-method="工厂类提供的工厂方法" factory-bean="工厂类的id" />

而读取该配置文件,创建并注入所需对象 的操作,都是按照如下的模板:

读取配置文件:

/* 获取ClassPathXmlApplicationContext对象 */
//以便我们之后通过这个对象进行 指定类的对象的注入
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

/* 获取指定类对象 的方式有两种 */
//格式1:
指定类 要被注入的对象 = context.getBean("配置文件中存储的id", 指定类.class);
//格式2:
指定类 要被注入的对象 = (指定类)context.getBean("配置文件中存储的id");

其实上述的格式,也不是很完善,
因为 一个程序会有多个类组成,
类于类之间会相互调用
比如service类会调用dao类的对象

那么,在我们之前的学习中,能够知道:
类的成员变量,一般有两种注入方式

  1. 使用setter方法对成员对象进行 注入
  2. 使用构造方法对成员对象进行 注入

那么,接下来,本人就来讲解下:
spring框架如何通过 这两种方式,来对成员对象进行注入:

成员对象的注入:

1. setter方法 式:

格式

<!--将参与依赖的bean对象交给spring容器-->
<bean id="成员对象类 的编号" class="成员对象类 的全路径名" />
<!--service中引用了userdao对象-->
<bean id="目标类" class="目标类 的全路径名" >
    <!--容器开始为目标类类的 成员属性 设置/注入 实现对象了-->
    <!--这就是依赖注入-->
    <property name="成员名称" ref="成员对象类 的编号" />
</bean>

(注意:成员名称一定要保证和目标类中setter方法后缀名称一致,
以便我们反射机制的调用)
例子
本人先来给出一个 将被注入依赖的类 —— SimpleClass类:

package edu.youzg.about_Spring.core;

/**
 * @Author: Youzg
 * @CreateTime: 2020-04-24 14:17
 * @Description:带你深究Java的本质!
 */
public class SimpleClass {
    private SimpleTwo simpleTwo;
    private SimpleThree simpleThree;

    public void setSimTwo(SimpleTwo simpleTwo) {
        this.simpleTwo = simpleTwo;
    }

    public void setSimpThree(SimpleThree simpleThree) {
        this.simpleThree = simpleThree;
    }

    public void doSomething() {
        System.out.println("Hello spring framework!");
    }

}

相应地,本人来给出配置文件:

<?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="simpleTwo" class="edu.youzg.about_Spring.core.SimpleTwo" />
    <bean id="simpleThree" class="edu.youzg.about_Spring.core.SimpleThree"/>

    <bean id="simpleClass" class="edu.youzg.about_Spring.core.SimpleClass">
        <property name="simpThree" ref="simpleThree" />
        <property name="simTwo" ref="simpleTwo"/>
    </bean>

</beans>

那么,现在本人来给出一个测试类:

package edu.youzg.about_Spring.core;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Author: Youzg
 * @CreateTime: 2020-04-22 23:05
 * @PROJECT: SpringStudy
 * @PACKAGE: edu.youzg.about_Spring
 * @Description:
 */
public class Demo {
    
    public static void main(String[] args){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        SimpleClass simpleClass = (SimpleClass) context.getBean("simpleClass");
        simpleClass.doSomething();
    }
    
}

现在,本人来展示下运行结果:
技术分享图片


2. 构造方法 式:

<bean id="userDao" class="com.lux.dao.UserDao" />
<bean id="userDaoOracle" class="com.lux.dao.UserDaoOracle" />
<!--service中引用了userdao对象-->
<!--javabean编写了有参数的构造方法,无参数的构造方法被覆盖,spring容器无法通过默认方式(无参数构造方法)创建javabean对象-->
<bean id="userService" class="com.lux.service.UserService" >
    <!--构造方法注入-->
     <constructor-arg  ref="userDaoOracle" />
</bean>

例子
本人先来给出一个将被注入依赖的类 —— SimpleClass类:

package edu.youzg.about_Spring.core;

/**
 * @Author: Youzg
 * @CreateTime: 2020-04-24 14:17
 * @Description:带你深究Java的本质!
 */
public class SimpleClass {

    private SimpleTwo simpleTwo;

    public SimpleClass(SimpleTwo simpleTwo) {
        this.simpleTwo = simpleTwo;
    }

    public void doSomething() {
        System.out.println("Hello spring framework!");
    }

}

那么,相应地,本人来给出 配置文件内容:

<?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="simpleTwo" class="edu.youzg.about_Spring.core.SimpleTwo" />
    <bean id="simpleThree" class="edu.youzg.about_Spring.core.SimpleThree"/>

    <bean id="simpleClass" class="edu.youzg.about_Spring.core.SimpleClass">
        <constructor-arg ref="simpleThree"></constructor-arg>
        <constructor-arg ref="simpleTwo"></constructor-arg>
    </bean>

</beans>

至于测试类,和上面的例子一样,不需要改变
那么,现在本人来展示下运行结果:
技术分享图片


【Spring框架学习】IOC/DI机制

原文:https://www.cnblogs.com/codderYouzg/p/12767402.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!