Spring框架IOC容器和DI依赖注入

这篇具有很好参考价值的文章主要介绍了Spring框架IOC容器和DI依赖注入。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Spring框架IOC容器和DI依赖注入

介绍

IOC(Invertion Of Control):控制反转,使用对象时,由使用new创建对象转变为由外部提供对象,此过程中对象的创建控制权由程序转移到外部的思想称之为控制反转.

DI(Dependency Injection):依赖注入,在容器中建立bean与bean之间的关系的过程,称之为依赖注入文章来源地址https://www.toymoban.com/news/detail-408362.html

入门案例

pom.xml依赖引入

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.shifan</groupId>
    <artifactId>spring-01-ioc-di-bean</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>
        <!--导入spring依赖,导入后才有spring类型的配置文件-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.1</version>
        </dependency>
    </dependencies>

</project>

BookDao

public interface BookDao {
    void save();
}

BookDaoImpl

public class BookDaoImpl implements BookDao {

    @Override
    public void save() {
        System.out.println("BookDao save...");
    }
}

BookService

public interface BookService {
    void save();
}

BookServiceImpl

public class BookServiceImpl implements BookService {

    private BookDao bookDao;

    //给spring容器注入提供set方法
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }

    @Override
    public void save() {
        bookDao.save();
    }
}

applicationContext.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,将该类对象的创建交由Spring容器管理
    id为bean的唯一标识,不可重复
    class为bean的类型,该属性不能写接口全类名,因为接口无法创建对象
    name为bean的别名,ref属性可以使用其他bean的别名,别名可以有多个,用逗号,空格,分号隔开都行
    scope为bean的作用范围,默认是singleton单例,可设置为prototype非单例
    若是有状态的对象,即该对象有成员变量用于存储数据,则不适合交给容器管理,可能存在线程安全问题
    spring通过反射获取类中的无参构造创建对象
    -->
    <bean id="bookDaoImpl" class="com.shifan.dao.impl.BookDaoImpl" name="bookDao"/>
    
    <!--
    配置service和dao的关系
    使用property标签配置当前bean中的的属性
    name="bookDao"中`bookDao`的作用是让Spring的IOC容器在获取到名称后,将首字母大写,前面加set找对应的`setBookDao()`方法进行对象注入
    ref为参照的容器中的bean
    autowire="byType" 按照类型自动注入,要求容器中相同类型的bean唯一
    autowire="byName"  按照名称注入,要求容器中有指定名称的bean,因变量名与配置耦合,不推荐使用
    自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效
    -->
    <bean id="bookServiceImpl" class="com.shifan.service.impl.BookServiceImpl" autowire="byType">
        <property name="bookDao" ref="bookDaoImpl"/>
    </bean>
</beans>

测试类

    //获取spring容器
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

    @Test
    public void testGetBean(){
        //获取bean
/*        BookDao bookDao = (BookDao) applicationContext.getBean("bookDaoImpl");
        bookDao.save();*/
        BookService bookServiceImpl = (BookService) applicationContext.getBean("bookServiceImpl");
        bookServiceImpl.save();
    }

    @Test
    public void testBeanAlias(){
        //根据别名获取bean
        BookDao bookDao = (BookDao) applicationContext.getBean("bookDao");
        bookDao.save();
    }

Bean实例化

静态工厂实例化

OrderDao
public interface OrderDao {
    void order();
}
OrderDaoImpl
public class OrderDaoImpl implements OrderDao {
    @Override
    public void order() {
        System.out.println("ordering orders...");
    }
}
OrderDaoFactory
package com.shifan.factory;

import com.shifan.dao.OrderDao;
import com.shifan.dao.impl.OrderDaoImpl;

public class OrderDaoFactory {
    public static OrderDao getOrderDao(){
        System.out.println("order dao service options...");//模拟对象创建前的必要业务操作
        return new OrderDaoImpl();
    }
}
applicatoinContext.xml
    <!--
    静态工厂实例化(了解)
    指定静态工厂类全类名及其创建对象的方法
    -->
    <bean id="orderDao" class="com.shifan.factory.OrderDaoFactory" factory-method="getOrderDao"/>
测试类
@Test
public void testStaticFactory(){
    //获取通过静态工厂创建的对象
    OrderDao orderDao = (OrderDao) applicationContext.getBean("orderDao");
    orderDao.order();
}

实例工厂实例化

UserDao
public interface UserDao {
    void save();
}
UserDaoImpl
public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("user dao save...");
    }
}
UserDaoFactory
public class UserDaoFactory {
    public UserDao getUserDao(){
        System.out.println("user dao service options...");//模拟对象创建前的必要业务操作
        return new UserDaoImpl();
    }
}
applicationContext.xml
    <!--
    实例工厂实例化(了解)
    配置实例工厂bean
    配置实例工厂创建的对象的bean:指定工厂bean,工厂创建bean的方法
    -->
    <bean id="userDaoFactory" class="com.shifan.factory.UserDaoFactory"/>
    <bean id="userDao" factory-method="getUserDao" factory-bean="userDaoFactory"/>
测试类
    @Test
    public void testInstanceFactory(){
        //获取通过实例工厂bean创建的对象
        UserDao userDao = (UserDao) applicationContext.getBean("userDao");
        userDao.save();
    }

使用实例工厂实现FactoryBean接口实例化

UserDaoFactoryBean
/**
 * 使用FactoryBean简化实例工厂方式实例化bean
 * FactoryBean还有一个方法boolean isSingleton()
 * 用于设置是否为单例,不重写则默认返回true,表示是单例
 */
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
    /**
     * 被重写后,在方法中进行对象的创建并返回
     * @return
     * @throws Exception
     */
    @Override
    public UserDao getObject() throws Exception {
        return new UserDaoImpl();
    }

    /**
     * 被重写后,主要返回的是被创建类的Class对象
     * @return
     */
    @Override
    public Class<?> getObjectType() {
        return UserDao.class;
    }

}

applicationContext.xml
    <!--
    使用实例工厂实现FactoryBean接口实例化bean(掌握)
    这种方式Spring整合其他框架时会用到
    -->
    <bean id="userDaoFactoryBean" class="com.shifan.factory.UserDaoFactoryBean"/>
测试类
    //使用FactoryBean简化
    @Test
    public void testFactoryBean(){
        UserDao userDao = (UserDao) applicationContext.getBean("userDaoFactoryBean");
        userDao.save();
    }

Bean的生命周期

BrandService

public interface BrandService {
    void save();
}

BrandServiceImpl

/**
 实现InitializingBean和DisposableBean接口,重写方法,简化初始化方法和销毁方法的编写与配置,实现bean生命周期控制(了解)
 */
public class BrandServiceImpl implements BrandService , InitializingBean, DisposableBean {

    private BrandDao brandDao;

    //使用构造器注入brandDao
    public BrandServiceImpl(BrandDao brandDao){
        this.brandDao = brandDao;
    }
    //使用set方法注入brandDao
/*    public void setBrandDao(BrandDao brandDao) {
        System.out.println("set...");
        this.brandDao = brandDao;
    }*/

    @Override
    public void save() {
        brandDao.save();
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("release resource...");
    }

    /*
    afterPropertiesSet:属性设置后
    即brandDao被注入后才执行
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("initialize resource...");
    }
}

BrandDao

public interface BrandDao {
    void save();
}

BrandDaoImpl

public class BrandDaoImpl implements BrandDao {

    private String name;
    private int price;

    public void setName(String name) {
        this.name = name;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    @Override
    public void save() {
        System.out.println("brand dao save..."+name+","+price);
    }
    //初始化方法
    public void init(){
        System.out.println("init resource...");
    }

    //销毁方法
    public void destroy(){
        System.out.println("rel resource...");
    }
}

applicatonContext.xml

	<!--
    bean的生命周期控制
    bean创建后方法:init-method,可用于初始化资源
    bean销毁前方法:destroy-method,可用于释放资源
    -->
    <bean id="brandDao" class="com.shifan.dao.impl.BrandDaoImpl" init-method="init" destroy-method="destroy">
        <!--普通参数注入-->
        <property name="name" value="飘柔"/>
        <property name="price" value="20"/>
    </bean>

    <bean id="brandService" class="com.shifan.service.impl.BrandServiceImpl">
        <!--<property name="brandDao" ref="brandDao"/>-->
        <!--
        构造器注入引用数据类型(name和ref)
        构造器也可用于注入普通参数(name和value)
        name属性需要保证和构造方法中的形参名一致,那么这就出现了耦合问题
        解决方案一:
        类型注入,使用type属性替换name属性,按照属性注入,但是当存在多个相同类型时就会无法精准注入
        方案二:
        索引注入,使用index属性替换name属性,按照索引下标0,1...注入,但当形参顺序发生变化时,又会出现耦合问题
        如何选择:
        强制依赖使用构造器注入,使用setter注入有概率不进行注入导致null对象出现
        强制依赖指对象创建过程中必须的参数
        可选依赖使用setter方法注入,灵活性更强
        可选依赖指对象创建过程中可有可无的参数
        自己开发的模块推荐使用setter注入
        -->
        <constructor-arg name="brandDao" ref="brandDao"/>
    </bean>

测试类

    @Test
    public void testBeanLifeCycle(){
/*        BrandDao brandDao = (BrandDao) applicationContext.getBean("brandDao");
        brandDao.save();*/
        BrandService brandService = (BrandService) applicationContext.getBean("brandService");
        brandService.save();
        /*
        调用ClassPathXmlApplicationContext类的close方法关闭容器
        避免IOC容器因为JVM退出而来不及销毁bean对象,导致销毁方法不执行
        ((ClassPathXmlApplicationContext)applicationContext).close();
         */

        /*
        注册钩子关闭容器
        在容器未关闭之前,设置回调函数,让JVM在退出之前回调此函数关闭容器
        与close方法相比:两种方法都能关闭容器,close方法是调用后就关闭容器,
        而registerShutdownHook方法是在JVM退出之前调用关闭容器
         */
        ((ClassPathXmlApplicationContext)applicationContext).registerShutdownHook();
    }

其他类型依赖注入

applicationContext.xml

    <!--
    集合注入
    - property标签表示setter方式注入,构造方式注入constructor-arg标签内部也可以写`<array>`、`<list>`、`<set>`、`<map>`、`<props>`标签
    - List的底层也是通过数组实现的,所以`<list>`和`<array>`标签是可以混用
    - 集合中要添加引用类型,只需要把`<value>`标签改成`<ref>`标签,这种方式用的比较少
    -->
    <!--
    数组类型数据
    <property name="array">
        <array>
            <value>100</value>
            <value>200</value>
            <value>300</value>
        </array>
    </property>
    -->
    <!--
    List类型数据
    <property name="list">
        <list>
            <value>itcast</value>
            <value>itheima</value>
            <value>boxuegu</value>
            <value>chuanzhihui</value>
        </list>
    </property>
    -->
    <!--
    set类型数据
    <property name="set">
    <set>
        <value>itcast</value>
        <value>itheima</value>
        <value>boxuegu</value>
        <value>boxuegu</value>
    </set>
    </property>
    -->
    <!--
    map类型数据
    <property name="map">
    <map>
        <entry key="country" value="china"/>
        <entry key="province" value="henan"/>
        <entry key="city" value="kaifeng"/>
    </map>
    </property>
    -->
    <!--
    Properties类型数据
    <property name="properties">
    <props>
        <prop key="country">china</prop>
        <prop key="province">henan</prop>
        <prop key="city">kaifeng</prop>
    </props>
    </property>
    -->

到了这里,关于Spring框架IOC容器和DI依赖注入的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Spring进阶系列丨第二篇】Spring中的两大核心技术IoC(控制反转)与DI(依赖注入)

    我们都知道Spring 框架主要的优势是在 简化开发 和 框架整合 上,至于如何实现就是我们要学习Spring 框架的主要内容,今天我们就来一起学习Spring中的两大核心技术IoC(控制反转)与DI(依赖注入)。 以经典的三层架构MVC作为案例,以前我们都是这么干的,看如下代码: 按照

    2024年02月05日
    浏览(66)
  • Spring6-IoC(Inversion of Control)控制反转和DI(Dependency Injection)依赖注入,手动实现IOC

    Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为 Java 语言的 反射机制 。简单来说, 反射机制指的是程序在运行时能够获取自身

    2024年02月09日
    浏览(59)
  • Java Spring IoC&DI :探索Java Spring中控制反转和依赖注入的威力,增强灵活性和可维护性

    💓 博客主页:从零开始的-CodeNinja之路 ⏩ 收录文章:Java Spring IoCDI :探索Java Spring中控制反转和依赖注入的威力,增强灵活性和可维护性 🎉欢迎大家点赞👍评论📝收藏⭐文章 我们一下要学习的内容都是为了实现⾼内聚低耦合来进行的 软件设计原则:⾼内聚低耦合. ⾼内聚指

    2024年04月15日
    浏览(46)
  • 【Spring框架二】——什么是Spring IOC、 什么是Spring 依赖注入

    【Spring框架一】——Spring框架简介 【Spring框架三】——Spirng IOC和DI的实现 本篇博客主要讲解的是Spring 的IOC以及DI(依赖注入)的基本概念和优势利弊,如果想知道如何实现Spring IOC与DI可以访问博主的另外一篇博客。 【Spring框架三】——Spirng IOC和DI的实现 它的核心思想是将对

    2024年02月06日
    浏览(46)
  • 【.NET6+WPF】WPF使用prism框架+Unity IOC容器实现MVVM双向绑定和依赖注入

    前言:在C/S架构上,WPF无疑已经是“桌面一霸”了。在.NET生态环境中,很多小伙伴还在使用Winform开发C/S架构的桌面应用。但是WPF也有很多年的历史了,并且基于MVVM的开发模式,受到了很多开发者的喜爱。 并且随着工业化的进展,以及几年前微软对.NET平台的开源,国内大多

    2024年02月06日
    浏览(59)
  • 【Spring】1、Spring 框架的基本使用【读取配置文件、IoC、依赖注入的几种方式、FactoryBean】

    Spring 框架可以说是 Java 开发中最重要的框架,功能 非常 强大 中文文档:https://springdoc.cn/spring/ 官网:https://spring.io/ Spring makes Java Simple、modern、productive … Spring 框架的几个核心概念: IoC: I nversion o f C ontrol:控制反转 DI: D ependency I njection:依赖注入 AOP: A spect O riented P rogram

    2024年02月09日
    浏览(63)
  • Spring IoC容器、IoC与DI

    目录 Spring是什么? 理解容器  什么是IoC(Inversion of Control) 传统的new创建对象的方式中类与类的耦合程度很大。  IoC的优势:  Spring IoC容器最核心的功能  什么是DI (Dependency Injection) IoC和DI的区别  Spring是指Spring Framework(Spring框架),它是开源的框架,有着很庞大的社区,通过

    2023年04月21日
    浏览(95)
  • Spring DI简介及依赖注入方式和依赖注入类型

    目录 一、什么是依赖注入 二、依赖注入方式 1. Setter注入 2. 构造方法注入 3. 自动注入  三、依赖注入类型 1. 注入bean类型 2. 注入基本数据类型 3. 注入List集合 4. 注入Set集合 5. 注入Map集合 6. 注入Properties对象 往期专栏文章相关导读  1. Maven系列专栏文章 2. Mybatis系列专栏文章

    2024年02月02日
    浏览(45)
  • Spring《三》DI 依赖注入

    🍎道阻且长,行则将至。🍓 上一篇:Spring《二》bean 的实例化与生命周期 下一篇:敬请期待 向一个类中传递数据的方式有: 普通方法(set 方法) 和 构造方法 。Spring 就相对应地为我们提供了两种注入方式: setter 注入 和 构造器注入 。同时也包括简单类型和引用类型(对象

    2023年04月21日
    浏览(42)
  • Spring 的依赖注入(DI)

    欢迎来到本篇文章,书接上回,本篇说说 Spring 中的依赖注入,包括注入的方式,写法,该选择哪个注入方式以及可能出现的循环依赖问题等内容。 如果正在阅读的朋友还不清楚什么是「依赖」,建议先看看我第一篇文章,通过 Employee 和 Department 简单说了什么是所谓的依赖。

    2024年02月11日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包