Spring一篇搞定!控制反转特性(IOC)详细笔记

控制反转(IOC)

是什么

控制反转(Inversion of Control,IoC)是一种设计思想,它的本质是将对象的创建、销毁、依赖关系的维护等控制权从程序代码中转移出去,交由容器来负责管理。在Java开发中,IoC意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。IoC容器负责创建对象、维护对象之间的关系,并在需要时注入依赖。

IoC的设计思想是:将原本在程序中手动创建对象的控制权,交由容器来管理。传统Java SE程序设计中,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由IoC容器来控制对象的创建。IoC容器控制了对象,主要控制了外部资源获取(不只是对象包括比如文件等)。

依赖注入(Dependency Injection,DI)是IoC的一种实现方式。DI是指组件之间依赖关系由容器在运行期决定,形象地说,即由容器动态地将某个依赖关系注入到组件之中。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

ioc的底层原理是 工厂设计模式+反射+xml解析

简单来说,对象由spring创建,属性也由spring来赋值。控制反转的核心是:将对象的创建权交出去,将对象和对象之间关系的管理权交出去,由第三方容器来负责创建与维护

为什么需要IOC

原来的三层架构,Dao层(连接数据库,做数据库的操作),service层(业务处理)和web层(调用service层的方法和前端做交互)代码之间耦合度太高,所以使用spring的ioc来管理对象,三层架构的设计违背了OCP(开闭原则)原则,即扩展应该是开放的,不应该造成原来代码的修改,对原来代码的修改关闭的。

实现方式:依赖注入(DI)

依赖:A对象和B对象有关系。注入:一种数据传递行为,用来让A和B对象产生关系

两种方式:set方法和构造方法

bean注入方式

set注入

基于set方法实现,底层会调用反射机制会调用属性对应的set方法来给属性赋值。要求实体类里面必须有对应属性的set方法

property标签的ref是要注入的Bean对象的id

有参构造方式

核心原理是调用有参构造器给属性赋值

通过测试得知,通过构造方法注入的时候:

  • 可以通过下标 index
  • 可以通过参数名 name
  • 也可以不指定下标和参数名,可以类型自动推断。

set注入细化

注入外部bean

bean定义到外面,在property标签使用ref注入属性,常用。

注入内部Bean

Bean标签里面嵌套Bean,这种方式作了解

<?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="userServiceBean" class="com.powernode.spring6.service.UserService">
        <property name="userDao">
            <bean class="com.powernode.spring6.dao.UserDao"/>
        </property>
    </bean>

</beans>
注入简单类型

需要特别注意:如果给简单类型赋值,使用value属性或value标签。而不是ref。

简单类型包括哪些呢?可以通过Spring的源码来分析一下:BeanUtils类

public class BeanUtils{
    
    //.......
    
    /**
	 * Check if the given type represents a "simple" property: a simple value
	 * type or an array of simple value types.
	 * <p>See {@link #isSimpleValueType(Class)} for the definition of <em>simple
	 * value type</em>.
	 * <p>Used to determine properties to check for a "simple" dependency-check.
	 * @param type the type to check
	 * @return whether the given type represents a "simple" property
	 * @see org.springframework.beans.factory.support.RootBeanDefinition#DEPENDENCY_CHECK_SIMPLE
	 * @see org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#checkDependencies
	 * @see #isSimpleValueType(Class)
	 */
	public static boolean isSimpleProperty(Class<?> type) {
		Assert.notNull(type, "'type' must not be null");
		return isSimpleValueType(type) || (type.isArray() && isSimpleValueType(type.getComponentType()));
	}

	/**
	 * Check if the given type represents a "simple" value type: a primitive or
	 * primitive wrapper, an enum, a String or other CharSequence, a Number, a
	 * Date, a Temporal, a URI, a URL, a Locale, or a Class.
	 * <p>{@code Void} and {@code void} are not considered simple value types.
	 * @param type the type to check
	 * @return whether the given type represents a "simple" value type
	 * @see #isSimpleProperty(Class)
	 */
	public static boolean isSimpleValueType(Class<?> type) {
		return (Void.class != type && void.class != type &&
				(ClassUtils.isPrimitiveOrWrapper(type) ||
				Enum.class.isAssignableFrom(type) ||
				CharSequence.class.isAssignableFrom(type) ||
				Number.class.isAssignableFrom(type) ||
				Date.class.isAssignableFrom(type) ||
				Temporal.class.isAssignableFrom(type) ||
				URI.class == type ||
				URL.class == type ||
				Locale.class == type ||
				Class.class == type));
	}
    
    //........
}

通过源码分析得知,简单类型包括:

  • 基本数据类型
  • 基本数据类型对应的包装类
  • String或其他的CharSequence子类
  • Number子类
  • Date子类
  • Enum子类
  • URI
  • URL
  • Temporal子类
  • Locale
  • Class
  • 另外还包括以上简单值类型对应的数组类型。
注入数组

<array>标签里面 value标签或者ref标签

要点:

  • 如果数组中是简单类型,使用value标签。
  • 如果数组中是非简单类型,使用ref标签。
注入集合

注意:注入List集合的时候使用list标签,如果List集合中是简单类型使用value标签,反之使用ref标签。

注入set集合

无序不可重复

要点:

  • 使用<set>标签
  • set集合中元素是简单类型的使用value标签,反之使用ref标签。
注入map集合

要点:

  • 使用<map>标签
  • 如果key是简单类型,使用 key 属性,反之使用 key-ref 属性。
  • 如果value是简单类型,使用 value 属性,反之使用 value-ref 属性。
注入properties

java.util.Properties继承java.util.Hashtable,所以Properties也是一个Map集合。key和value都是字符串

要点:

  • 使用<props>标签嵌套<prop>标签完成。
  • prop带name 标签之间是value
注入null和空字符串

注入空字符串使用:<value/> 或者 value=""

注入null使用:<null/> 或者 不为该属性赋值

注入的值含有特殊符号

解决方案包括两种:

  • 第一种:特殊符号使用转义字符代替。

  • 第二种:将含有特殊符号的字符串放到:<![CDATA[ 内容]]> 当中。因为放在CDATA区中的数据不会被XML文件解析器解析。
<property name="result">
  <!--只能使用value标签-->
  <value><![CDATA[2 < 3]]></value>
</property>
P命名空间的注入

目的是简化配置,不用再使用Property标签了,对set注入的简化,实体类需要setter方法

xml里面配置头部信息 xmlns:p="http://www.springframework.org/schema/p"

然后编写Bean标签 格式 p:属性="值"

<bean id="Ptest" class="com.lch.pojo.Ptest" p:name="lch" p:id="10"></bean>

编写测试程序

@Test
public void test1(){
    ApplicationContext Context = new ClassPathXmlApplicationContext("beans.xml");
    Ptest ptest = (Ptest) Context.getBean("Ptest");
    System.out.println(ptest);
}
c命名空间注入(构造方法注入)

目的是简化配置,简化构造方法注入方式 实体类需要配置构造方法

xml里面配置头部信息 xmlns:c="http://www.springframework.org/schema/c"

<bean id="CTest" class="com.lch.pojo.CTest" c:_0="C命名空间注入" c:_1="1"></bean>
util命名空间

可以让配置复用

spring配置文件里配置头部信息,实体类需要set方法

xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

基于xml的自动装配

autowire指定自动装配方式

根据名称装配(byName)

这说明,如果根据名称装配(byName),底层会调用set方法进行注入。

例如:setAge() 对应的名字是age,setPassword()对应的名字是password,setEmail()对应的名字是email。

userService有个userDao对象 名字为aaa 而set方法为setAaa 和bean id ="aaa"对应 可以实现自动注入

<bean id="userService" class="com.powernode.spring6.service.UserService" autowire="byName"/>
    
    <bean id="aaa" class="com.powernode.spring6.dao.UserDao"/>
根据类型自动装配(byType)

基于set方法,某种Bean的类型必须是唯一的

<!--byType表示根据类型自动装配-->
    <bean id="accountService" class="com.powernode.spring6.service.AccountService" autowire="byType"/>

    <bean class="com.powernode.spring6.dao.AccountDao"/>

IOC创建对象的方式(Bean对象创建方式)

bean标签配置方法

<bean id= class = >

bean的id和class属性:

  • id属性:代表对象的唯一标识。可以看做一个人的身份证号。
  • class属性:用来指定要创建的java对象的类名,这个类名必须是全限定类名(带包名)。

<property name= value=>标签

根据下标,根据名字

默认无参构造的方式

配置文件加载时,容器中管理的对象就已经初始化了。

要让spring创建对象,必须有无参构造,spring使用无参构造创建对象的原理:利用反射机制创建

// dom4j解析beans.xml文件,从中获取class的全限定类名
// 通过反射机制调用无参数构造方法创建对象
Class clazz = Class.forName("com.powernode.spring6.bean.User");
Object obj = clazz.newInstance();

Bean对象的作用域(scope属性)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

多种方法求1+12+123+1234……

有网友出了一道题&#xff1a; 从键盘输入一个小于10的正整数n&#xff0c;计算1121231234……&#xff0c;即前n项之和。 第一眼看到题目&#xff0c;直觉告诉我必须使用嵌套的两个for循环&#xff0c;里面的循环生成每一项&#xff0c;外面的循环求和。错误的方向和思路让我…

LAMMPS单层石墨烯拉伸(velocity)

本文主要把之前学习石墨烯拉伸velocity拉伸做个总结。 一、模拟环境参数设置 units metal # 使用"metal"单位&#xff0c;这是 LAMMPS 中的一种长度单位 dimension 3 # 模拟的维度为三维空间 boundary s p p # 周期性边界条件&am…

商店数据(八)

目录 57.后台权限表 58.推荐记录表 ​59.系统上传资源表 ​60.角色表 ​61.订单结算表 62.店铺表 63.店铺认证表 64.店铺申请&#xff08;移动端&#xff09;表 57.后台权限表 CREATE TABLE wat_privilgeid (privilegeod int(11) NOT NULL AUTO_INCREMENT COMMENT 自增…

数据结构——哈希表的平均查找长度

我们要首先知道哈希表是干什么的&#xff0c;哈希表并不是为了单纯存储数据的&#xff0c;他并不会减小存储这些数据使用的空间&#xff0c;而是为了实现快速的数据查找&#xff0c;插入和删除操作。map就可以使用哈希表来实现&#xff0c;所以map可以实现利用键来快速访问到值…

2024年最新 Windows\Linux 后台运行程序注解

一、前言 有时候需要在后台运行程序&#xff0c;查了查网上现有的程序有些运行不了&#xff0c;跑通了之后简单记录一下&#xff0c;为后面的同学躺一下雷 1、Linux 系统 Linux后台运行进程时&#xff0c;通常使用如下方法&#xff1a; &#xff08;1&#xff09;程序挂后台…

Spring Bean依赖注入-Spring入门(二)

1、SpringBean概述 在Spring中&#xff0c;一切Java对象都被视为Bean&#xff0c;用于实现某个具体功能。 Bean的依赖关系注入的过程&#xff0c;也称为Bean的装配过程。 Bean的装配方式有3种&#xff1a; XML配置文件注解Java类 Spring中常用的两种装配方式分别是基于XML的…

[嵌入式系统-52]:RT-Thread:RT-Thread Studio工程的文件结构

目录 一、RT-Thread Studio概述 二、RT-Thread Studio工程架构 2.1 目录结构 2.2 软件包管理 2.3 硬件电路板信息 2.3 可执行文件elf信息 2.4 系统头文件 2.5 应用程序目录 2.6 硬件驱动程序 2.7 RT Thread操作系统程序 2.7.1 component&#xff1a;应用程序组件 …

PD虚拟机和双系统哪个好 Mac建议装双系统吗

在当今数字化时代&#xff0c;对于部分使用Mac电脑的用户来说&#xff0c;选择如何在系统中运行Windows或其他操作系统能节省大量精力。Parallels Desktop&#xff08;PD&#xff09;虚拟机和双系统是两种常见的选择&#xff0c;它们各自具有优势和限制。下面我们来看看PD虚拟机…

【MyBatis】(动态SQL <if> 标签 <trim>标签 <where>标签<set>标签<foreach>标签<include>标签)

文章目录 动态SQL< if > 标签< trim> 标签< where> 标签< set> 标签< foreach> 标签< include> 标签 动态SQL 在MyBatis框架中&#xff0c;动态SQL是一个强大的特性。它允许我们根据不同的条件动态的组装SQL语句&#xff0c;能够灵活的发…

【pycharm】调试模式中四个常用按钮介绍

【pycharm】调试模式中四个常用按钮介绍 在 PyCharm 的调试模式中&#xff0c;有四个常用的按钮&#xff0c;它们的功能如下&#xff1a; Step Over (F8)&#xff1a;单步执行&#xff0c;但在遇到函数调用时&#xff0c;不会进入函数内部&#xff0c;而是将整个函数作为一步执…

UVa12313 A Tiny Raytracer

UVa12313 A Tiny Raytracer 题目链接题意分析AC 代码 题目链接 UVA - 12313 A Tiny Raytracer 题意 给出 《训练指南》题意翻译 本题的任务是实现一个小型光线追踪渲染器。场景由若干三角形网格&#xff08;triangle mesh&#xff09;组成&#xff0c;有且仅有一个点光源&…

三苯基膦以及副产物的处理方式

参考文献&#xff1a; Easy Removal of Triphenylphosphine Oxide from Reaction Mixtures by Precipitation with CaBr2 | Organic Process Research & Development (acs.org) Triphenylphosphine Oxide Removal from Reactions: The Role of Solvent and Temperature |…

分享一些实用的工具

1、amCharts5&#xff1a;模拟航线飞行/业务分布图/k线/数据分析/地图等 网址&#xff1a; JavaScript mapping library: amCharts 5https://www.amcharts.com/javascript-maps/ Demo地址&#xff1a;Chart Demos - amChartshttps://www.amcharts.com/demos/#maps 他分为amC…

[华为OD] 给航天器一侧加装长方形或正方形的太阳能板 100

给航天器一侧加装长方形或正方形的太阳能板&#xff08;图中的红色斜线区域&#xff09;&#xff0c;需要先安装两个支 柱&#xff08;图中的黑色竖条&#xff09;&#xff0c;再在支柱的中间部分固定太阳能板。但航天器不同位置的支柱长度 不同&#xff0c;太阳能板的安装面…

学习笔记-数据结构-线性表(2024-04-18)- 单向链表选择排序

试以单向链表为存储结构实现简单选择排序的算法。 实现递增排序&#xff0c;首先选择一个元素作为第一个比较值&#xff0c;遍历其他所有的元素&#xff0c;如果发现其他元素中有比它小的元素&#xff0c;则交换两个元素&#xff0c;这样每一趟都能找到符合要求的最小值 正经…

selenium 自动化测试课上实操指南1——百度搜索

1.环境准备 下面的所有资源可以从超星班级资料中下载&#xff0c;机房的同学在收到的文件夹中可以找到文件 非本校同学&#xff0c;免费加入学银在线课程&#xff0c;就可以在资料 根目录 > 02 课件新 > week09 web自动化测试02 里下载本次实操资料 1&#xff09;安…

K8S探针分享

一&#xff0c;探针介绍 1 探针类型 livenessProbe&#xff1a;存活探针&#xff0c;用于判断容器是不是健康&#xff1b;如果探测失败&#xff0c;Kubernetes就会重启容器。 readinessProbe&#xff1a;就绪探针&#xff0c;用于判断是否可以将容器加入到Service负载均衡池…

使用Tortoise 创建远程分支

1。首先创建本地分支branch1&#xff0c;右键tortoise git->创建分支&#xff0c;输入分支名称branch1&#xff0c;确定。 2。右键tortoise git->推送&#xff0c;按下图设置&#xff0c;确定&#xff0c;git会判断远程有没有分支branch1&#xff0c;如果没有会自动创建…

C++学习随笔(11)——vector

本章我们来学习一下vector&#xff01; 目录 1.vector的介绍及使用 1.1 vector的介绍 1.2 vector的使用 1.2.1 vector的定义 1.2.2 vector iterator 的使用 1.2.3 vector 空间增长问题 1.2.4 vector 增删查改 1.2.5 vector 迭代器失效问题。 1.vector的介绍及使用 1…

ANSYS WorkBench基础说明

1引入CAE产品设计流程 2有限元法简介 有限元法的基本概念:把一个原来是连续的物体划分为有限个单元&#xff0c;这些单元通过有限个节点相互连接&#xff0c;承受与实际载荷等效的节点载荷&#xff0c;根据力的平衡条件进行分析&#xff0c;并根据变形协调条件把这些单元重新组…
最新文章