JAVA的是什么ioc_spring中ioc是什么

article/2025/9/10 20:03:22

IoC——Inversion of Control,控制反转

在Java开发中,IoC意味着将你设计好的类交给系统去控制,而不是在你的类内部控制。IoC是一种让服务消费者不直接依赖于服务提供者的组件设计方式,是一种减少类与类之间依赖的设计原则。

DI——Dependency Injection(依赖注入)

即组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中。

依赖注入的目标并非为软件系统带来更多的功能,而是为了提升组件重用的概率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务 逻辑,而不用关心具体的资源来自何处、由谁实现。

1:控制反转:

谁控制谁?控制什么?为何叫反转(对应于正向)?哪些方面反转了 ?为何需要反转?

2:依赖:

什么是依赖(按名词理解,按动词理解)?谁依赖于谁?为什么需要依赖?依赖什么东西?

3:注入:

谁注入于谁?注入什么东西?为何要注入?

4:依赖注入和控制反转是同一概念吗?

5:参与者都有哪些?

6:IoC/DI是什么?能做什么?怎么做?用在什么地方?

还不能完全回答和理解,没有关系,先来看看IoC/DI的基本思想演变,然后再回头来回答这些问题

2d523ad00309ca4006362eec5b376a44.png

92b972734f40d010d9e6c4b5184f509a.png

9c79366f106bdffd6dbcdfcbbd178b1a.png

b58a4c7f4a162cacd7e44f6a914ddbbc.png

0eb92df7bbac4370f41ff16572877b00.png

IoC容器

简单的理解就是:实现IoC思想,并提供对象创建、对象装配以及对象生命周期管理的软件就是IoC容器。

IoC理解

1:应用程序无需主动new对象;而是描述对象应该如何被创建即可

IoC容器帮你创建,即被动实例化;

2:应用程序不需要主动装配对象之间的依赖关系,而是描述需要哪个服务

IoC容器会帮你装配(即负责将它们关联在一起),被动接受装配;

3:主动变被动,体现好莱坞法则:别打电话给我们,我们会打给你

4:体现迪米特法则(最少知识原则):应用程序不知道依赖的具体实现,只知道需要提供某类服务的对象(面向接口编程);并松散耦合,一个对象应当对其他对象有尽可能少的了解,不和陌生人(实现)说话

5:是一种让服务消费者不直接依赖于服务提供者的组件设计方式,是一种减少类与类之间依赖的设计原则。

efd1c179289a70b6431457f57e2f4150.png

使用IoC/DI容器开发需要改变的思路

1:应用程序不主动创建对象,但要描述创建它们的方式。

2:在应用程序代码中不直接进行服务的装配,但要描述哪一个组件需要哪一项服务,由容器负责将这些装配在一起。

也就是说:所有的组件都是被动的,组件初始化和装配都由容器负责,应用程序只是在获取相应的组件后,实现应用的功能即可。

提醒一点

IoC/DI是思想,不是纯实现技术。IoC是框架共性,只是控制权的转移,转移到框架,所以不能因为实现了IoC就叫IoC容器,而一般除了实现了IoC外,还具有DI功能的才叫IoC容器,因为容器除了要负责创建并装配组件关系,还需要管理组件生命周期。

n工具准备

1:Eclipse + Jdk6.0 ,示例用的Eclipse是Eclipse Java EE IDE for Web Developers,Version: Helios Service Release 1

2:spring-framework-3.1.0.M2-with-docs.zip

构建环境

1:在Eclipse里面新建一个工程,设若名称是Spring3test

2:把发行包里面的dist下面的jar包都添加到Eclipse里面

3:根据Spring的工程来获取Spring需要的依赖包,在联网的情况下,通过Ant运行projects/build-spring-framework/build.xml,会自动去下载所需要的jar包,下载后的包位于projects/ivy-cache/repository下面。

4:为了方便,把这些jar包也添加到Eclipse里面

开发接口

java代码:

public interface HelloApi {

public String helloSpring3(int a);

}

开发实现类

java代码:

public class HelloImpl implements HelloApi{

public String helloSpring3(int a){

System.out.println("hello Spring3==="+a);

return "Ok,a="+a;

}

}

配置文件

1:在src下面新建一个文件叫applicationContext.xml

2:在Spring发行包里面搜索一个例子,比如使用:projects\org.springframework.context\src\test\java\org\springframework\jmx下的applicationContext.xml,先把里面的配置都删掉,留下基本的xml定义和根元素就可以了,它是一个DTD版的,而且还是2.0版的。

建议使用Spring3的Schema版本,示例如下:

java代码:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="

http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd

http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd

http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd

">

………………………

4:配置applicationContext.xml如下:

java代码:

编写客户端如下:

java代码:

package com.bjpowernode.Spring3.hello;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Client {

public static void main(String[] args) {

ApplicationContext context = new ClassPathXmlApplicationContext(

new String[] {"applicationContext.xml"});

HelloApi api = (HelloApi)context.getBean("helloBean");

String s = api.helloSpring3(3);

System.out.println("the s="+s);

}

}

审视和结论

1:所有代码中(除测试代码之外),并没有出现Spring的任何组件 。

2:客户代码(这里就是我们的测试代码)仅仅面向接口编程,而无需知道实现类的具体名称。同时,我们可以很简单的通过修改配置文件来切换具体的底层实现类 。

结论

1:首先,我们的组件并不需要实现框架指定的接口,因此可以轻松的将组件从Spring脱离,甚至不需要任何修改(这在基于EJB架实现的应用中是难以想象的)。

2:其次,组件间的依赖关系减少,极大改善了代码的可重用性和可维护性

3:面向接口编程

什么是Spring中的Bean

在Spring中,那些组成应用的主体及由Spring IoC容器所管理的对象被称之为bean。简单地讲,bean就是由Spring容器初始化、装配及被管理的对象,除此之外,bean就没有特别之处了(与应用中的其他对象没有什么区别)。而bean定义以及bean相互间的依赖关系将通过配置元数据来描述。

为什么使用Bean这个名字

使用‘bean'这个名字而不是‘组件'(component) 或‘对象'(object)的动机源于Spring框架本身(部分原因则是相对于复杂的EJB而言的)。

Spring的IoC容器

org.springframework.beans.factory.BeanFactory是Spring IoC容器的实际代表者,IoC容器负责容纳bean,并对bean进行管理。

Spring IoC容器将读取配置元数据;并通过它对应用中各个对象进行实例化、配置以及组装。通常情况下我们使用简单直观的XML来作为配置元数据的描述格式。在XML配置元数据中我们可以对那些我们希望通过Spring IoC容器管理的bean进行定义。

IoC/DI是Spring最核心的功能之一, Spring框架所提供的众多功能之所以能成为一个整体正是建立在IoC的基础之上

BeanFactory和ApplicationContext

org.springframework.beans及org.springframework.context包是Spring IoC容器的基础。BeanFactory提供的高级配置机制,使得管理任何性质的对象成为可能。 ApplicationContext是BeanFactory的扩展,功能得到了进一步增强,比如更易与Spring AOP集成、消息资源处理(国际化处理)、事件传递及各种不同应用层的context实现(如针对web应用的WebApplicationContext)。

接口选择之惑

在实际应用中,用户有时候不知道到底是选择BeanFactory接口还是ApplicationContext接口。但是通常在构建JavaEE应用时,使用ApplicationContext将是更好的选择,因为它不仅提供了BeanFactory的所有特性,同时也允许使用更多的声明方式来得到我们想要的功能。

简而言之,BeanFactory提供了配制框架及基本功能,而ApplicationContext则增加了更 多支持企业核心内容的功能。ApplicationContext完全由BeanFactory扩展而来,因而BeanFactory所具备的能力和行为也适用于ApplicationContext。

bac042ab787b0795515f5db68fe424f2.png

Spring IoC容器的实例化非常简单,如下面的例子:

1:第一种:

java代码:

Resource resource = new FileSystemResource("beans.xml");

BeanFactory factory = new XmlBeanFactory(resource);

2:第二种:

java代码:

ClassPathResource resource = new ClassPathResource("beans.xml");

BeanFactory factory = new XmlBeanFactory(resource);

3:第三种:

java代码:

ApplicationContext context = new ClassPathXmlApplicationContext(

new String[] {"applicationContext.xml", "applicationContext-part2.xml"});

// of course, an ApplicationContext is just a BeanFactory

BeanFactory factory = (BeanFactory) context;

读取多个配置文件

第一种方法:

为了加载多个XML文件生成一个ApplicationContext实例,可以将文件路径作为字符串数组传给ApplicationContext构造器。而bean factory将通过调用bean defintion reader从多个文件中读取bean定义。通常情况下,Spring团队倾向于上述做法,因为这样各个配置并不会查觉到它们与其他配置文件的组合。

第二种方法:

使用一个或多个的元素来从另外一个或多个文件加载bean定义。所有的元素必须放在元素之前以完成bean定义的导入。 让我们看个例子:

java代码:

配置文件中常见的配置内容

1f91645218ddc6d592284ac4ad9f529c.png

在IoC容器内部,bean的定义由BeanDefinition 对象来表示,该定义将包含以下信息:

1:全限定类名:这通常就是已定义bean的实际实现类。如果通过调用static factory方法来实例化bean,而不是使用常规的构造器,那么类名称实际上就是工厂类的类名。

2:bean行为的定义,即创建模式(prototype还是singleton)、自动装配模式、依赖检查模式、初始化以及销毁方法。这些定义将决定bean在容器中的行为。

3:用于创建bean实例的构造器参数及属性值。比如使用bean来定义连接池,可以通过属性或者构造参数指定连接数,以及连接池大小限制等。

4:bean之间的关系,即协作 (或者称依赖)。

Bean的命名

每个bean都有一个或多个id(或称之为标识符或名称,在术语上可以理解成一回事),这些id在当前IoC容器中必须唯一。

当然也可以为每个bean定义一个name,但是并不是必须的,如果没有指定,那么容器将为其生成一个惟一的name。对于不指定name属性的原因我们会在后面介绍(比如内部bean就不需要)。

Bean命名的约定

bean的命名采用标准的Java命名约定,即小写字母开头,首字母大写间隔的命名方式。如accountManager、 accountService等等。

对bean采用统一的命名约定将会使配置更加简单易懂。而且在使用Spring AOP,这种简单的命名方式将会令你受益匪浅。

Bean的别名

一个Bean要提供多个名称,可以通过alias属性来加以指定 ,示例如下:

容器如何实例化Bean

当采用XML描述配置元数据时,将通过元素的class属性来指定实例化对象的类型。class属性主要有两种用途:在大多数情况下,容器将直接通过 反射调 用指定类的构造器来创建bean(这有点等类似于在Java代码中使用new操作符);在极少数情况下,容器将调用类的静态工厂方法来创建bean实例,class属性将用来指定实际具有静态工厂方法的类(至于调用静态工厂方法创建的对象类型是当前class还是其他的class则无关紧要)。

用构造器来实例化Bean ,前面的实例就是

使用静态工厂方法实例化

采用静态工厂方法创建bean时,除了需要指定class属性外,还需要通过factory-method属性来指定创建bean实例的工厂方法,示例如下:

class="examples.ExampleBean2"

factory-method="createInstance"/>

使用实例工厂方法实例化

使用此机制,class属性必须为空,而factory-bean属性必须指定为当前(或其祖先)容器中包含工厂方法的bean的名称,而该工厂bean的工厂方法本身必须通过factory-method属性来设定,并且这个方法不能是静态的,示例如下:

使用容器

从本质上讲,BeanFactory仅仅只是一个维护bean定义以及相互依赖关系的高级工厂接口。使用getBean(String)方法就可以取得bean的实例;BeanFactory提供的方法极其简单。n依赖注入(DI) 背后的基本原理

是对象之间的依赖关系(即一起工作的其它对象)只会通过以下几种方式来实现: 构造器的参数、 工厂方法的参数,或 给由构造函数或者工厂方法创建的对象设 置属性。

因此,容器的工作就是创建bean时注入那些依赖关系。相对于由bean自己来控制其实例化、直接在构造器中指定依赖关系或则类似服务定位器(Service Locator)模式这3种自主控制依赖关系注入的方法来说,控制从根本上发生了倒转,这也正是控制反转IoC名字的由来。

应用依赖注入(DI)的好处、

应用DI原则后,代码将更加清晰。而且当bean自己不再担心对象之间的依赖关系(以及在何时何地指定这种依赖关系和依赖的实际类是什么)之后,实现更高层次的 松耦合将易如反掌。

依赖注入(DI)基本的实现方式

DI主要有两种注入方式,即 Setter注入和 构造器注入。

通过调用无参构造器或无参static工厂方法实例化bean之后,调用该bean的setter方法,即可实现基于setter的DI。 示例如下:

示例——Java类

java代码:

public class HelloImpl implements HelloApi{

private String name = "";

public void setName(String name){

this.name = name;

}

public String helloSpring3(int a){

System.out.println("hello Spring3==="+a+",name="+name);

return "Ok,a="+a;

}

}

示例——配置文件

bjpowernode Spring3

示例——Java类

java代码:

public class HelloImpl implements HelloApi{

private String name = "";

public HelloImpl(String name){

this.name = name;

}

public String helloSpring3(int a){

System.out.println("hello Spring3==="+a+",name="+name);

return "Ok,a="+a;

}

}

示例——配置文件

java代码:

bjpowernode Spring3

默认解析方式

构造器参数将根据类型来进行匹配。如果bean定义中的构造器参数类型明确,那么bean定义中的参数顺序就是对应构造器参数的顺序

构造器参数类型匹配

可以使用type属性来显式的指定参数所对应的简单类型。例如:

java代码:

构造器参数的索引

使用index属性可以显式的指定构造器参数出现顺序。例如:

java代码:

构造器参数的名称

在Spring3里面,可以使用构造器参数的名称来直接赋值。例如:

java代码:

直接量(基本类型、Strings类型等)

元素通过字符串来指定属性或构造器参数的值。JavaBean属性编辑器将把字符串从java.lang.String类型转化为实际的属性或参数类型。示例:

java代码:

oracle.jdbc.driver.OracleDriver

jdbc:oracle:thin:@localhost:1521:orcl

test

Value可以做为子元素或者是属性使用。

nidref元素

idref元素用来将容器内其它bean的id传给 或 元素,同时提供错误验证功能。 idref元素和差不多,只是传递 一个字符串,用来方便xml检查。示例如下:

java代码:

上述bean定义片段完全地等同于(在运行时)以下的片段

theTargetBean

idref元素 续

第一种形式比第二种更可取的主要原因是,使用idref标记允许容器在部署时 验证所被引用的bean是否存在。而第二种方式中,传给client bean的targetName属性值并没有被验证。任何的输入错误仅在client bean实际实例化时才会被发现(可能伴随着致命的错误)。如果client bean 是prototype类型的bean,则此输入错误(及由此导致的异常)可能在容器部署很久以后才会被发现。

如果被引用的bean在同一XML文件内,且bean名字就是bean id,那么可以使用local属性,此属性允许XML解析器在解析XML文件时来对引用的bean进行验证 ,示例如下:

引用其它的bean(协作者) ——ref元素

尽管都是对另外一个对象的引用,但是通过id/name指向另外一个对象却有三种不同的形式,不同的形式将决定如何处理作用域及验证。

1:第一种形式也是最常见的形式是使用标记指定目标bean,示例:

2:第二种形式是使用ref的local属性指定目标bean,它可以利用XML解析器来验证所引用的bean是否存在同一文件中。示例:

3:第三种方式是通过使用ref的parent属性来引用当前容器的父容器中的bean,并不常用。示例:

java代码:

class="org.springframework.aop.framework.ProxyFactoryBean">

内部Bean

所谓的内部bean(inner bean)是指在一个bean的或 元素中使用元素定义的bean。内部bean定义不需要有id或name属性,即使指定id 或 name属性值也将会被容器忽略。示例:

java代码:


http://chatgpt.dhexx.cn/article/VVNKd43o.shtml

相关文章

java中ioc作用_java中的ioc是什么

java中的ioc是什么 发布时间:2020-06-03 20:01:10 来源:亿速云 阅读:174 作者:Leah java中的ioc是什么相信大部分人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,话不多说,一起往下看吧。 什么是ioc ioc全称是【Inversion of Control】控制反转,按照字面意…

1、重写TextView的onDraw方法

Android重写系统TextView Git源码地址: https://github.com/AndroidAppWidgetDemo/Android_Widget_CustomTextView 一、目的 重写Android系统TextView,是为了解决系统TextView中文换行所带来的参差不齐的锯齿效果。如图1.1为系统TextView的绘制结果&am…

getX()、getRawX()、getTranslationX()、gettranslationX()...

关于屏幕上获取这些位置的情况应该分为两种,一种是在没有点击屏幕时,另外一种是有点击 我们来分别看看这几个X在图形上的直观表示和解释 有点击时的getX() getY() getX()表示触摸点距离view本身左边界的距离getY()表示触摸点距离…

Direct2D函数DWrite

Win8 DirectX 11.1 中 Direct3D 和 Direct2D , DirectWrite 的交互比11方便多了,不用创建什么DX10.1的device,不用搞什么设备同步,直接往同一个DXGI Resource里写就是了。 这大概得益于Win 6.2 底层架构的进一步融合,…

Pthreads on Microsoft Windows

Posix Threads API (pthreads) 是在并行编程中用到的非常普通的API,这套API包括许多非常基础的同步方法,方便我们编写高效的多线程程序。然而,Microsoft Windows 并不包含这样的接口。幸运的是,这里有一个开源的Windows平台上的 P…

Text-Instance Graph: Exploring the Relational Semantics for Text-based Visual Question Answering

Text-Instance Graph: Exploring the Relational Semantics for Text-based Visual Question Answering 文章目录 Text-Instance Graph: Exploring the Relational Semantics for Text-based Visual Question AnsweringAbstract1. Introduction2. Related works2.1. Visual Que…

绘制系列(五)-DrawText()详解

绘制系列(五)-DrawText()详解 文字基础知识 1、setTextAlign() 设置文字对齐方式(起始点相对于文字) canvas.drawText(“文字”,起始点,paint) 比如: paint.setTextAlign(Paint.Align.RIGH…

Windows API一日一练(24)DrawText函数-绘制矩形内的文字

主目录传送门 https://blog.csdn.net/zb774095236/article/details/108291755 本次学习的源码模板下载: 1.百度云:https://pan.baidu.com/s/1B0YuPWgSxvLTHk59STzQQQ 提取码:1ins 学习目标: 在Win32API-13-14-窗口关闭和窗口…

wpf-绘制文字:DrawText和DrawGlyphRun

先上效果&#xff1a;上面的Hello,world是DrawGlyphRun绘制的&#xff0c;下面的hello是DrawText绘制的。绘制的结果都是不能复制的。 前台 <local:CanvasCustom x:Name"myCanvas"/>后台 class CanvasCustom : Canvas {protected override void OnRender(Dr…

android 文字drawable,TextDrawable

TextDrawable 是一个可以将纯文本生成Drawable的类库&#xff0c;你可以将这个Drawable设置给ImageView&#xff0c;从而可将文字转为图片。这在某些场合是很有用的。 效果图&#xff1a; 如何使用你可在xml中创建个ImageView android:layout_width"60dp" android:la…

drawText用法总结

drawText 经常使用Canvas的draw***方法去绘制一些图像图形&#xff0c;绘制的坐标是从Canvas左上角开始计算的&#xff0c;如果想要把一个图像放到某个位置&#xff0c;直接drawBitmap传递图片左上角的坐标就行了。那drawText就不一样&#xff0c;如果你传递进去字符串&#x…

drawText详解

Canvas 作为绘制文本时&#xff0c;是以基线为基准绘制的&#xff0c;不是左上角 FontMetrics对象 它以四个基本坐标为基准&#xff0c;分别为&#xff1a; ・FontMetrics.top ・FontMetrics.ascent ・FontMetrics.descent ・FontMetrics.bottom ascent和top都为负数&#xff…

B. The Monster and the Squirrel

B. The Monster and the Squirrel Ari the monster always wakes up very early with the first ray of the sun and the first thing she does is feeding her squirrel. Ari draws a regular convex polygon on the floor and numbers it’s vertices 1, 2, …, n in cloc…

Springboot整合squirrel-foundation状态机

目录 一. 快速入门 1 . maven 2 . 快速开始 3 . Fluent Api 4 . 状态机四要素 5 . 状态机构建器 6 . 状态机转换操作(代码配置方式) 7 . 状态机转换操作(注解声明方式) 8 . 上下文不敏感状态机 二 : 使用注意事项 P1 : 异常 : StateMachineBuilderImpl cannot fi…

Hive的客户端界面工具–SQuirrel SQL Client--详细安装以及连接Hive过程

SQuirrel SQL Client是一款支持Hive的可视化工具&#xff0c;是市面上少数支持Hive中比较好用的&#xff0c;看下如何安装使用吧&#xff0c;下面是非常详细的安装过程。 1.下载客户端 SQuirrel SQL Client的官网及下载地址为&#xff1a;http://squirrel-sql.sourceforge.ne…

Linux安装SQuirreL SQL Client

环境和准备 操作系统&#xff1a; Ubuntu 20.04SQuirreL&#xff1a; squirrel-sql-snapshot-20220326_1238-standard.jarDb2 driver&#xff1a; db2jcc4.jardb2jcc_license_cu.jar MySQL driver&#xff1a; mysql-connector-java-8.0.27.jar 下载和安装 首先下载SQuirreL…

智能优化算法之松鼠算法(Squirrel search algorithm)

文章目录 背景Squirrel search algorithm(SSA)SSARandom initialization&#xff08;随机初始化&#xff09;Fitness evaluation&#xff08;适应值评价&#xff09;Sorting, declaration and random selection&#xff08;排序、声明和随机选择&#xff09;Generate new locat…

electron打包遇到 Making for target: squirrel - On platform: win32 - For arch: x64错误

上面横线处是出现错误的位置。报错的原因如下&#xff1a; 1、package.json的“author”和“description”在打包时是必填内容&#xff0c;随便填些内容即可打包成功。 2、和项目的绝对路径有关&#xff0c;项目的绝对路径不能出现中文&#xff0c;否则在红线处会报错。

WPF 使用Squirrel自动更新应用

前言 本文简单的介绍了如何使用 Squirrel 来为 WPF 客户端 进行自动检查更新。 Squirrel git 地址 &#xff1a;http:// https://github.com/Squirrel/Squirrel.Windows 本文使用了 Visual Studio 2022 进行演示讲解。 参考英文博客&#xff1a; https://intellitect.com/d…

SQuirrel SQL Client的安装

如果您的工作要求您在一天之中连接许多不同的数据库 &#xff08;oracle、DB2、mysql、postgresql、Sql Server等等&#xff09;&#xff0c;或者你经常需要在多个不同种类的数据库之间进行数导入导出。那么SQuirreL SQL Client 将会是比较理想的数据库客户端链接工具。 简单介…