【Spring】核心部分之IOC:通过列举代码例子,从底层刨析,深入源码,轻轻松松理解Spring的核心IOC,IOC有这一篇足以

news2024/11/29 2:37:30

IOC

  • 一,概念和原理
    • 1.概念:控制反转
    • 2.原理:(xml解析,工厂模式,反射)
    • 3.IOC接口:两个主要容器实现类(加载xml配置文件)
  • 二,操作Bean管理
    • 1.基于 xml 配置文件方式实现
      • (1)基于 xml 方式创建对象
      • (2)基于 xml 方式注入属性
        • 方式一:使用 set 方法进行注入
        • 方式二:使用有参数构造进行注入
        • 补充:xml 注入其他类型属性
        • 方式三:p 名称空间注入
        • 方式四:xml 自动装配
    • 2.基于注解方式实现
      • (1)基于注解方式实现对象创建
      • (2)基于注解方式实现属性注入
    • 3.完全注解开发
  • 三,Bean 作用域
  • 四,Bean 生命周期
  • 五,Spring中Bean的类型

一,概念和原理

1.概念:控制反转

IOC:控制反转,把对象创建和对象之间的调用过程,交给 Spring 进行管理
使用 IOC 目的:为了耦合度降低,简化开发

2.原理:(xml解析,工厂模式,反射)

xml 解析:
工厂模式:
反射:关于反射内容
见Java中反射的理解及如何使用——精简

3.IOC接口:两个主要容器实现类(加载xml配置文件)

BeanFactory:IOC 容器基本实现,是 Spring 内部的使用接口,不提供开发人员进行使用,加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象
ApplicationContext:BeanFactory 接口的子接口,提供更多更强大的功能,一般由开发人员进行使用加载配置文件时候就会把在配置文件对象进行创建

当写好xml配置文件后,通过加载配置文件来创建对象

在这里插入图片描述

代码举例

public class TestSpring {
    /**
     * bean1.xml:src目录下的配置文件
     * User:类
     * user:配置文件中的id,也就是User类的别名
     */
    @Test
    public void testUser(){
       //1.加载spring的配置文件
        ApplicationContext context=new ClassPathXmlApplicationContext("bean1.xml") ;
        //2.获取配置创建的对象
        User user = context.getBean("user", User.class);
    }
}

二,操作Bean管理

Bean 管理指的是两个操作
(1)Spring 创建对象
(2)Spirng 注入属性

1.基于 xml 配置文件方式实现

(1)基于 xml 方式创建对象

创建spring的配置文件

<?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="studentOne" class="com.li.Student"></bean>
</beans>

在 spring 配置文件中,使用 bean 标签,标签里面添加对应属性,就可以实
现对象创建.在 bean 标签有很多属性
id 属性:唯一标识
class 属性:类全路径(包类路径)
创建对象时候,默认也是执行无参数构造方法完成对象创建

代码举例:

<bean id="studentOne" class="com.li.Student"></bean>

获取对象的三种方式:

1.根据bean的id来获取

Student studentOne = (Student) context1.getBean("studentOne");

2.根据bean的类型

Student studentOne = context1.getBean(Student.class);

当根据bean的类型获取时,容器中有且只能有一个类型匹配的bean

3.根据bean的id和类型来获取

Student studentOne = context1.getBean("studentOne", Student.class);

(2)基于 xml 方式注入属性

DI:依赖注入,就是注入属性

方式一:使用 set 方法进行注入

1.需要提供属性对应的set方法

public class Book {
    private String bname;
    private String bauthor;

    public void setBname(String bname) {
        this.bname = bname;
    }

    public void setBauthor(String bauthor) {
        this.bauthor = bauthor;
    }

    public Book() {
    }
}

2.在 spring 配置文件配置对象创建,配置属性注入
使用 property 完成属性注入
name:类里面属性名称
value:向属性注入的值

<bean id="book" class="com.li.Spring.Book">
        <property name="bname" value="及你太美"></property>
        <property name="bauthor" value="蔡徐坤"></property>
    </bean>

方式二:使用有参数构造进行注入

1.创建类,定义属性,创建属性对应有参数构造方法

public class Book {
    private String bname;
    private String bauthor;


    public Book(String bname, String bauthor) {
        this.bname = bname;
        this.bauthor = bauthor;
    }
    }

2.在 spring 配置文件中进行配置

<bean id="book" class="com.li.Spring.Book">
        <constructor-arg name="bname" value="及你太美"></constructor-arg>
        <constructor-arg name="bauthor" value="蔡徐坤"></constructor-arg>
    </bean>

补充:xml 注入其他类型属性

1.字面量

null:

<bean id="book" class="com.li.Spring.Book">
        <property name="bname" value="葵花宝典"></property>
        <property name="bauthor" >
            <null/>
        </property>
    </bean>

属性值包含特殊符号:

<property name="bname">
 <value><![CDATA[<<蔡徐坤>>]]></value>
</property>

2.注入属性-外部 bean

(1)创建两个类 service 类和 dao 类
(2)在 service 调用 dao 里面的方法
(3)在 spring 配置文件中进行配置

<bean id="service" class="com.li.Spring.Service">
    <property name="dao" ref="dao"></property>
</bean>
    <bean id="dao" class="com.li.Spring.Dao"></bean>

3.注入属性-内部 bean

<bean id="emp" class="com.li.spring.bean.Emp">
 <!--设置两个普通属性-->
 <property name="ename" value="lucy"></property>
 <property name="gender" value="女"></property>
 <!--设置对象类型属性-->
 <property name="dept">
 <bean id="dept" class="com.li.spring.bean.Dept">
 <property name="dname" value="安保部"></property>
 </bean>
 </property>
</bean>

4.注入属性-级联赋值

第一种写法:

<bean id="emp" class="com.li.spring.bean.Emp">
 <!--设置两个普通属性-->
 <property name="ename" value="lucy"></property>
 <property name="gender" value="女"></property>
 <!--级联赋值-->
 <property name="dept" ref="dept"></property>
</bean>
<bean id="dept" class="com.li.spring.bean.Dept">
 <property name="dname" value="财务部"></property>
</bean>

第二种写法

<bean id="emp" class="com.li.spring.bean.Emp">
 <!--设置两个普通属性-->
 <property name="ename" value="lucy"></property>
 <property name="gender" value="女"></property>
 <!--级联赋值-->
 <property name="dept" ref="dept"></property>
 <property name="dept.dname" value="技术部"></property>
</bean>
<bean id="dept" class="com.li.spring.bean.Dept">
 <property name="dname" value="财务部"></property>
</bean>

5.xml 注入集合属性

1、注入数组类型属性
2、注入 List 集合类型属性
3、注入 Map 集合类型属性

<bean id="stu" class="com.li.spring.collectiontype.Stu">
 <!--数组类型属性注入-->
 <property name="courses">
 <array>
 <value>java 课程</value>
 <value>数据库课程</value>
 </array>
 </property>
 <!--list 类型属性注入-->
 <property name="list">
 <list>
 <value>张三</value>
 <value>小三</value>
 </list>
 </property>
 <!--map 类型属性注入-->
 <property name="maps">
 <map>
 <entry key="JAVA" value="java"></entry>
 <entry key="PHP" value="php"></entry>
 </map>
 </property>
 <!--set 类型属性注入-->
 <property name="sets">
 <set>
 <value>MySQL</value>
 <value>Redis</value>
 </set>
 </property>
</bean>

<对象属性值>

<bean id="course1" class="com.li.spring.collectiontype.Course">
 <property name="cname" value="Spring 框架"></property>
</bean>
<bean id="course2" class="com.li.spring.collectiontype.Course">
 <property name="cname" value="MyBatis 框架"></property>
</bean>
<!--注入 list 集合类型,值是对象-->
<property name="courseList">
 <list>
 <ref bean="course1"></ref>
 <ref bean="course2"></ref>
 </list>
</property>

方式三:p 名称空间注入

使用 p 名称空间注入,可以简化基于 xml 配置方式
1.添加 p 名称空间在配置文件中
2.进行属性注入,在 bean 标签里面进行操作

方式四:xml 自动装配

自动装配:根据当前指定的策略 ,在ioc容器中匹配某个bean,自动为bean中的类的属性或接口类型的属性赋值
可以通过bean标签中的autowire属性自动装配
no,default:表示不装配

传统的注入方法:

<bean id="userController" class="com.li.controller.userController">
       <property name="userservice" ref="userviceimp"></property>
   </bean>

    <bean id="userviceimp" class="com.li.service.imp.userviceimp">
        <property name="userdao" ref="userdao"></property>
    </bean>

    <bean id="userdao" class="com.li.dao.imp.userdaoimp"></bean>

byType:
根据要赋值属性的类型,在ioc容器中匹配某个bean,为属性赋值

 <bean id="userController" class="com.li.controller.userController" autowire="byType">
   </bean>
    <bean id="userviceimp" class="com.li.service.imp.userviceimp" autowire="byType">
    </bean>
    <bean id="userdao" class="com.li.dao.imp.userdaoimp"></bean>

byName
一般不用
将要赋值的属性的属性名作为bean的id在容器中匹配某个bean,为属性赋值

<bean id="userController" class="com.li.controller.userController" autowire="byType">
   </bean>
    <bean id="userviceimp" class="com.li.service.imp.userviceimp" autowire="byName">
    </bean>
    <bean id="userdao" class="com.li.dao.imp.userdaoimp"></bean>
    <bean id="dao" class="com.li.dao.imp.userdaoimp"></bean>

2.基于注解方式实现

什么是注解
(1)注解是代码特殊标记,格式:@注解名称(属性名称=属性值, 属性名称=属性值…)
(2)使用注解,注解作用在类上面,方法上面,属性上面
(3)使用注解目的:简化 xml 配置

(1)基于注解方式实现对象创建

Spring 针对 Bean 管理中创建对象提供注解
(1)@Component:将类标识为普通组件
(2)@Service:将类标识为业务层组件
(3)@Controller:将类标识为控制层组件
(4)@Repository:将类标识为持久层组件
上面四个注解功能是一样的,都可以用来创建 bean 实例

举例:

第一步:开启组件扫描

<context:component-scan base-package="com.li.spring"></context:component-scan>

第二步:创建类,在类上面添加创建对象注解

@Repository
public class UserDaoImpl implements UserDao {
}

通过注解加扫描配置的id,默认值为类的小驼峰,即类的类名为小写的结果,可以通过在注解后面修改,即通过标识组件的注解的value属性值来设置自定义的id

(2)基于注解方式实现属性注入

(1)@Autowired:根据属性类型进行自动装配

能够标识的位置:
1.成员变量
2.set方法:如果成员变量有对应的set方法,直接标到set方法上也能注入
3.为当前成员变量赋值的有参构造方法上
原理:
默认使用byType的方式,在ioc容器中通过类型匹配某个bean为属性赋值

第一步 把 service 和 dao 对象创建,在 service 和 dao 类添加创建对象注解

第二步 在 service 注入 dao 对象,在 service 类添加 dao 类型属性,在属性上面使用注解

@Controller
public class UserController {
    @Autowired
    private UserService userService;
    public void save(){
        userService.save();
    }
}

(2)@Qualifier:根据名称进行注入
这个@Qualifier 注解的使用,和上面@Autowired 一起使用

(3)@Resource:可以根据类型注入,可以根据名称注入

3.完全注解开发

(1)创建配置类,替代 xml 配置文件

举例:

@Configuration //将当前类作为配置类
@ComponentScan(basePackages = {"com.li.spring"}) //开启组件扫描
public class SpringConfig {

}

(2)编写测试类

举例:

public void TestTwo(){
        //加载配置类
        ApplicationContext contextTwo =new AnnotationConfigApplicationContext(SpringConfig.class);
        UserController bean = contextTwo.getBean(UserController.class);
        bean.save();

    }

三,Bean 作用域

作用域:在Spring 里面,设置创建 bean 实例是单实例还是多实例
在 Spring 里面,默认情况下,bean 是单实例对象

设置单实例还是多实例:设置 scope 值:singleton 或 prototype

singleton 和 prototype 区别
第一 :
singleton 单实例,prototype 多实例
第二 :
设置 scope 值是 singleton 时候,加载 spring 配置文件时候就会创建 单实例对象
设置 scope 值是 prototype 时候,不是在加载 spring 配置文件时候创建 对象,在调用getBean 方法时候创建多实例对象

代码演示:

单例

在这里插入图片描述

多例

在这里插入图片描述

四,Bean 生命周期

1、生命周期
(1)从对象创建到对象销毁的过程
2、bean 生命周期
(1)通过构造器创建 bean 实例(无参数构造)
(2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
(3)调用 bean 的初始化的方法(需要进行配置初始化的方法)
(4)bean 可以使用了(对象获取到了)
(5)当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)

五,Spring中Bean的类型

1、Spring 有两种类型 bean,一种普通 bean,另外一种工厂 bean(FactoryBean)
2、普通 bean:在配置文件中定义 bean 类型就是返回类型
3、工厂 bean:在配置文件定义 bean 类型可以和返回类型不一样

第一步 创建类,让这个类作为工厂 bean,实现接口 FactoryBean
第二步 实现接口里面的方法,在实现的方法中定义返回的 bean 类型

package com.li.factor;

import com.li.dao.pojo.user;
import org.springframework.beans.factory.FactoryBean;

public class userFactor implements FactoryBean<user> {
    @Override
    public user getObject() throws Exception {
        return new user();
    }

    @Override
    public Class<?> getObjectType() {
        return user.class;
    }
}
<?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 class="com.li.factor.userFactor">

     </bean>
</beans>

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/3480.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

React - 实现瀑布流加载

React - 实现瀑布流加载一. 瀑布流实现1.1 处理重复请求问题一. 瀑布流实现 先来看下原本的效果&#xff0c;一次性加载完所有的信息然后展示&#xff1a; 其次&#xff0c;我们需要去监听这个滚轮的滚动事件&#xff0c;那么React页面就可以添加一个监听器&#xff1a; use…

SpringSecurity Oauth2实战 - 04 自定义AuthProvider实现登录认证

文章目录1. 搭建资源服务器1. Token存储配置类 TokenStoreAutoConfiguration2. 资源服务器配置类 ResourceServerAutoConfiguration3. 在META-INF/spring.factories文件下添加配置类2. 搭建授权服务器1. 密码加密配置类 PasswordEncodeConfig2. RestTemplateConfig3. 授权服务器…

k3s 离线部署指南

文章目录1. 简介2. Docker 手动部署镜像方式2.1 安装docker2.2 导入镜像2.3 安装 k3s2.4 查看3. Containerd 手动部署镜像方式3.1 导入镜像到 containerd 镜像列表3.2 授予可执行权限3.3 安装 K3s4. Containerd 私有镜像仓库方式4.1 配置 K3s 镜像仓库4.2 授予可执行权限4.3…

集合(Set)和有序集合(ZSet)的基本使用方法详解【Redis】

文章目录一. Redis中的集合(Set)1.1基本的一些操作1.1.1 smembers查看集合中的所有成员1.1.2 scard删除成员数量1.1.3 smove移动成员1.1.4 sinterstore 存储俩个集合的交集二.Redis中的有序集合(ZSet)2.1 基本的一些操作2.1.1 zadd添加1到多个成员2.1.2 zcount 返回指定分数区间…

【HarmonyOS】鸿蒙轻量级智能穿戴应用可以集成华为分析SDK吗?

1、问题描述 我们的项目是基于鸿蒙系统开发的轻量级智能穿戴应用&#xff0c;目前在做的主要是运动手表GT3。 我们在项目中使用了华为分析服务&#xff0c;但是在Build Hap时出现问题&#xff1a; 因此&#xff0c;我们想了解轻量级智能穿戴应用项目中是否能够集成华为分析服…

计算机毕业设计(附源码)python在线影评系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

Leetcode-每日一题1106. 解析布尔表达式(DFS模拟栈)

题目链接&#xff1a;点击跳转 思路 方法一、DFS模拟栈 题目意思很简单让你去判断与或非布尔表达式的结果&#xff0c;我们可以看布尔表达式看成一棵树&#xff0c;需要我们解决的是从最底层的嵌套布尔表达式产生的结果不断向上的结果&#xff0c;如图&#xff1a; 既然他是…

云栖大会开源重磅升级!PolarDB-X v2.2: 企业级和国产化适配

2022 年云栖大会上&#xff0c;PolarDB-X 发布 2.2.0 版本&#xff0c;这是一个重要的里程碑版本&#xff0c;重点推出符合分布式数据库金融标准下的企业级和国产化适配&#xff0c;共包括八大核心特性&#xff0c;全面提升 PolarDB-X 分布式数据库在金融、通讯、政务等行业的普…

自定义分页器

文章目录自定义分页器1、分页推导2、分页器代码封装自定义分页器 1、分页推导 queryset对象支持切片操作 确定用户访问的页码 url?page1 current_pagerequest.GET.get(page,1)前端获取到 的都是字符串数据&#xff0c;需要类型转换 current_page request.GET.get(page,…

为什么C语言执行效率高,运行快?

目录 简述C语言由来 BCPL语言及代码B语言以及代码C语言 编程语言 机器语言汇编语言高级语言 C为何快速 简述 都说C语言编写的程序执行效率比较高&#xff0c;那么到底高在哪里&#xff0c;我们一块来学习学习。 C语言由来 C语言源自于BCPL、B两种语言。 BCPL语言以及代码…

django csrfMiddleware的一些理解跨站和跨域

术语 术语解释备注跨域两个 URL 的“协议主机名端口”3者只要有一个不一致http://www.taobao.com/和https://www.taobao.com/跨站两个 URL 的 eTLD1 不相同a.github.io 和 b.github.ioeTLDeffective top level domain &#xff08;有效顶级域名&#xff09;.com、.co.uk、.git…

第六节:数组的定义与使用【java】

目录 &#x1f4c3;1. 数组的基本概念 1.1 为什么要使用数组 1.2 什么是数组 1.3 数组的创建及初始化 1.4 数组的使用 &#x1f392;2. 数组是引用类型 2.1 初始JVM的内存分布 2.2 基本类型变量与引用类型变量的区别 2.3 认识 null 2.4 再谈引用变量 &#x1f4d6;3. …

Redis的RDB持久化配置以及数据恢复

文章目录Redis的RDB持久化配置以及数据恢复配置RDB持久化机制RDB持久化机制的工作流程基于RDB持久化机制的数据恢复Redis的RDB持久化配置以及数据恢复 配置RDB持久化机制 在 redis 的配置文件中找到如下内容&#xff1a; 以 save 60 10000 为例&#xff0c;表示每隔 60s&…

Springboot 整合与文件配置

哈喽~大家好&#xff0c;这篇看看Springboot 整合与文件配置。 &#x1f947;个人主页&#xff1a;个人主页 &#x1f948; 系列专栏&#xff1a;【Java框架】 &#x1f949;与这篇相关的文章&#xff1a; 【JAVAEE框架】MyBatis与Spring的整合&#xff0…

Unity-huatuo热更新调研

文章目录1. 相关资料2. 环境准备2.1 项目和编辑器版本2.2 安装huatuo插件2.3 在build settings里面勾选Export Project2.4 导出Android studio工程3. 验证热更新3.1 更改读取目录3.2 运行android apk3.3 热更新1. 相关资料 bilibili视频&#xff1a;https://www.bilibili.com/…

学院打卡第十四天

今天是一道困难题&#xff0c;难得有困难题&#xff01;&#xff01; 如题&#xff1a; 但是这个困难题感觉也不是很”困难“&#xff01;&#xff01;&#xff01; 算法思想&#xff1a; 第一感觉就是利用栈的思想&#xff0c;这种题做多了&#xff0c;一看见就是想到栈&…

2021年上半年软件设计师下午真题及答案解析(三)

阅读下列说明和图&#xff0c;回答问题1至问题3&#xff0c;将解答填入答题纸的对应栏内。 【说明】 某中医医院拟开发一套线上抓药APP&#xff0c;允许患者凭借该医院医生开具的处方线上抓药&#xff0c;并提供免费送药上门服务。该系统的主要功能描述如下&#xff1a; &#…

Kotlin编程实战——概述(01)

一 概述 Kotlin用于服务器开发Kotlin 进行 Android 开发Kotlin 用于 JavaScript 开发Kotlin 用于原生开发Kotlin 用于数据科学协程多平台 二 Kotlin用于服务器开发 2.1 原因 表现力可伸缩性互操作性迁移迁移工具学习曲线 2.2 Kotlin 进行服务器端开发的框架 Spring、Vert.…

Premiere 出现“该级别的帧大小/帧速率无效。请减小视频范围或帧速率,或者增加配置文件和级别,然后重试”的解决办法

有时候我们需要制作一定纵横比的视频&#xff0c;比如设置画面大小为1080(水平)1920(垂直)的竖屏尺寸&#xff0c;但是最近我导出视频时发现了 “该级别的帧大小/帧速率无效。请减小视频范围或帧速率&#xff0c;或者增加配置文件和级别&#xff0c;然后重试” 这个问题&#x…

使用插值法公式组成数字电路进行计算的计算机

使用插值法公式组成数字电路进行计算的计算机 使用插值法公式组成数字电路进行计算的计算机是一种可以使用插值法计算积分值&#xff0c;导数值&#xff0c;函数值的数字计算机&#xff0c;它由按键&#xff0c;液晶显示器&#xff0c;中央处理器组成。按键输入的程序保存在磁带…