一.IOC/DI概念

参考博客:https://www.cnblogs.com/xdp-gacl/p/4249939.html

IOC(inversion of control, 控制反转)是一种设计思想,而不是一种技术. IOC意味着将我们设计好的对象交给容器控制,而不是交给对象内部控制.它指导我们设计出松耦合,更优良的程序. 传统程序都是由在类内部主动创建依赖对象来使用, 从而导致类与类之间高耦合, 难于测试; 有了IOC容器,把创建和查找依赖对象的控制权交给了容器, 由容器进行注入组合对象,所以对象和对象之间是松耦合, 这样使得程序的整个体系结构非常灵活.

实际上,IOC可以看做是一个大型中介, 将对象的信息登记其中,这个对象是什么, 这个对象又需要什么 ,由中介公司给对象分配它需要的资源, 以及将对象分配给需要它的对象.Spring在这个过程中控制着对象的生命周期和对象间的关系, 所有类的创建和销毁都由Spring控制, 而不是需要它们的类控制, 这就是控制反转.

DI(Dependency Injection, 依赖注入)是IOC的一个重点,它实现IOC的一种方法,或者说DI是IOC的另一种说法 , 它负责实现IOC动态地向某个对象提供它所需要的其他对象. 比如一个人需要一根扫把, 不是由这个人自己去做扫把, 而是由Spring将做好的扫把给他,  而这个人全程需要做的,就是喊我要一根扫把. 什么叫做依赖, 人需要扫把, 人就对扫把有了依赖. 而DI就是根据这个依赖,将扫把分配给这个人的.

二.IOC的使用

参考博客:https://www.cnblogs.com/best/p/5727935.html#_lab2_0_4

IOC实现的两种方式: XML配置  ,  Spring注解

    依赖注入的两种形式: Setter依赖注入, 构造方法依赖注入 

1.XML配置的两种依赖注入形式:

(1)Setter依赖注入: 首先创建一个Book类,将其属性设置好setter,getter方法

public class Book {
private int id;
private String name;
private User user; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public User getUser() {
return user;
} public void setUser(User user) {
this.user = user;
}
}

然后在applicationContext.xml中添加bean, 告诉Spring两者的依赖关系,实现注入

    <bean name="book" class="pojo.Book">
<property name="name" value="book1"></property>
<property name="user" ref="user"></property> <!--这里将book依赖了user,因此在我们获取book时,会获取指定的user对象 -->
</bean> <bean name="user" class="pojo.User">
<property name="name" value="user1"></property>
<property name="age" value="12"></property>
</bean>

(2)构造方法依赖注入:

我们将BOOK类中添加了一个两个参数的构造方法,然后在xml文件中确定两个参数的值,从而让spring容器能够创造对象

public class Book {
private int id;
private String name;
private User user; //Constructor
public Book(String name,User user){
this.name = name;
this.user = user;
}
}

xml文件中的配置为: 指定了构造器有两个参数, 第一个参数是String , 第二个参数指向了另一个bean

    <bean name="book" class="pojo.Book">
<constructor-arg type="java.lang.String"> <!-- 指定参数的类型,可以在有多个构造器时不产生歧义 -->
<value>Adel</value>
</constructor-arg>
<constructor-arg>
<ref bean="user"></ref>
</constructor-arg>
</bean> <bean name="user" class="pojo.User">
<property name="name" value="user1"></property>
<property name="age" value="12"></property>
</bean>

或者可以这样写构造参数:

    <bean name="book" class="pojo.Book">
<constructor-arg name="name" value="lala"></constructor-arg>
<constructor-arg name="user" ref="user"></constructor-arg>
</bean>

又或者这样写:

    <bean name="book" class="pojo.Book">
<constructor-arg index="0" value="lala"></constructor-arg>
<constructor-arg index="1" ref="user"></constructor-arg>
</bean>

(3) Scope对象作用域:  从Spring容器中获取的对象的作用域可以修改,默认的作用域为单例, 具体如下

  • Singleton :  每个Spring容器作用域中,一个bean定义 只对应一个对象实例
  • Prototype:  一个bean定义对应多个对象实例
  • Request:    一个bean定义作用于HTTP request 生命周期, 指每个HTTP request 从Spring获取的对象实例不一样. 仅在基于web的Spring ApplicationContext中有效.
  • Session:    一个bean定义作用域HTTP session 生命周期,
  • Global Session:      一个bean定义作用域全局的HTTP session 生命周期.
  • Application:       一个bean定义作用于整个ServletContext生命周期

其在配置中写在bean的属性Scope中:

    <bean name="book" class="pojo.Book" scope="singleton">
<constructor-arg index="0" value="lala"></constructor-arg>
<constructor-arg index="1" ref="user"></constructor-arg>
</bean>

(4)延迟初始化bean:    通常ApplicationContext默认在启动时将所有singleton bean提前实例化. 通常提前实例化是好事,避免某些错误因为延迟实例化而不被提前发现. 但是如果想防止提前实例化, 比如你只需要用到book对象, 而不需要它初始化它的user对象, 就可以用lazy-init属性来控制

    <bean name="book" class="pojo.Book" >
<constructor-arg index="0" value="lala"></constructor-arg>
<constructor-arg index="1" ref="user"></constructor-arg>
</bean> <bean name="user" class="pojo.User" lazy-init="true">
<property name="name" value="user1"></property>
<property name="age" value="12"></property>
</bean>

(5)回调方法:  初始化回调函数init

public class Book {
private int id;
private String name;
private User user; // Constructor
public Book(String name,User user){
this.name = name;
this.user = user;
} public void init(){
System.out.println("创建了一本书");
} public void destroy(){
System.out.println("销毁了一本书");
}
}

在xml文件中设置初始化回调函数,就会在创建时调用

    <bean name="book" class="pojo.Book" init-method="init" destroy-method="destroy" >
<constructor-arg index="0" value="lala"></constructor-arg>
<constructor-arg index="1" ref="user"></constructor-arg>
</bean>

2.Spring注解:

注解会削减一些配置的工作量, 但是代码的耦合度会增加,  应当根据需要使用注解

(1)@Component注解:  这个注解和<bean>作用类似, 通过增加@Component()注解中的参数,指定其在Spring容器中的名称. 如果不写,则是默认其在Spring容器中的名称为类名的小写 如User类 在Spring容器中默认名称为 user

@Component("user")
public class User {
private int id;
private int age;
private String name; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} }

在配置文件中,即使没有user这个bean , 其它bean也可以用到

    <bean name="book" class="pojo.Book" init-method="init" destroy-method="destroy" >
<constructor-arg index="0" value="lala"></constructor-arg>
<constructor-arg index="1" ref="user"></constructor-arg>
</bean> <!--<bean name="user" class="pojo.User" lazy-init="true">-->
<!--<property name="name" value="user1"></property>-->
<!--<property name="age" value="12"></property>-->
<!--</bean>-->

(2)@Auotowired 注解:   在Spring中,可以使用 @Autowired 注解通过setter方法,构造函数或字段自动装配Bean。

 
 
通过setter方法
public class Book {
private int id;
private String name;
private User user; public User getUser() {
return user;
} @Autowired
public void setUser(User user) {
this.user = user;
}
public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} }

这样,即使在applicationContext.xml文件中没有设置要在book中user依赖哪个对象, Spring容器也会自动装配

    <bean name="book" class="pojo.Book"  >
<property name="name" value="lala"></property>
<property name="id" value="12"></property>
</bean> <bean name="user" class="pojo.User" lazy-init="true">
<property name="name" value="user1"></property>
<property name="age" value="12"></property>
</bean>

通过构造函数:

public class Book {
private int id;
private String name;
private User user; // Constructor
@Autowired
public Book(User user){
this.user = user;
}
}

通过字段:

public class Book {
private int id;
private String name;
@Autowired
private User user;
}

(3)@Resource注解  : 这个注解与@Autowired不同是, 它可以指定装配对象的名称,或者类型,或者两者都指定

如book和user

@Component("u")
public class User {
private int id;
private int age;
private String name;
//setter 和 getter
}
@Component("b")
public class Book {
private int id;
private String name;
@Resource(name = "u")
private User user;
//setter和getter
}
@Component("b")
public class Book {
private int id;
private String name;
@Resource(name = "u",type = User.class)
private User user;
}

或者这样

@Component("b")
public class Book {
private int id;
private String name;
@Resource(name = "u",type = User.class)
private User user;
 
各种注解的解释, 以下转自 https://www.cnblogs.com/best/p/5727935.html#_lab2_0_4

@Service用于注解业务层组件(我们通常定义的service层就用这个)

@Controller用于注解控制层组件(如struts中的action)

@Repository用于注解数据访问组件,即DAO组件

@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行注解。

装配注解主要有:@Autowired、@Qualifier、@Resource,它们的特点是:

1、@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入;

2、@Autowired默认是按照类型装配注入的,如果想按照名称来转配注入,则需要结合@Qualifier一起使用;

3、@Resource注解是由J2EE提供,而@Autowired是由spring提供,故减少系统对spring的依赖建议使用@Resource的方式;如果Maven项目是1.5的JRE则需换成更高版本的。

4、@Resource和@Autowired都可以书写注解在字段或者该字段的setter方法之上

5、@Autowired 可以对成员变量、方法以及构造函数进行注释,而 @Qualifier 的注解对象是成员变量、方法入参、构造函数入参。

6、@Qualifier("XXX") 中的 XX是 Bean 的名称,所以 @Autowired 和 @Qualifier 结合使用时,自动注入的策略就从 byType 转变成 byName 了。

7、@Autowired 注释进行自动注入时,Spring 容器中匹配的候选 Bean 数目必须有且仅有一个,通过属性required可以设置非必要。

8、@Resource装配顺序
  8.1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
  8.2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
  8.3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
  8.4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;

以下转自博客:https://blog.csdn.net/qq_22583741/article/details/79589910

1.@Component取代<bean class="">
@Component("id") 取代 <bean id="" class="">
2.web开发,提供3个@Component注解衍生注解(功能一样)取代
@Repository :dao层
@Service:service层
@Controller:web层
3.依赖注入,给私有字段设值,也可以给setter方法设值

普通值:@Value(" ")
引用值:
方式1:按照【类型】注入
@Autowired
方式2:按照【名称】注入1
@Autowired
@Qualifier("名称")
方式3:按照【名称】注入2
@Resource("名称")
4.生命周期
初始化:@PostConstruct
销毁:@PreDestroy
5.作用域
@Scope("prototype") 多例
注解使用前提,添加命名空间,让spring扫描含有注解类

Spring框架-IOC/DI详细学习的更多相关文章

  1. Spring框架——IOC&DI

    Spring Spring 目标 内容 Spring与web整合的原理 Spring 中包含的关键特性 Spring架构图 企业级框架 企业级系统 IOCDI IOC DI IOC和DI 为什么使用依 ...

  2. Spring框架IOC容器和AOP解析 非常 有用

    Spring框架IOC容器和AOP解析   主要分析点: 一.Spring开源框架的简介  二.Spring下IOC容器和DI(依赖注入Dependency injection) 三.Spring下面 ...

  3. 自己动手写Spring框架--IOC、MVC

    对于一名Java开发人员,我相信没有人不知道 Spring 框架,而且也能够轻松就说出 Spring 的特性-- IOC.MVC.AOP.ORM(batis). 下面我想简单介绍一下我写的轻量级的 S ...

  4. Spring入门IOC和AOP学习笔记

    Spring入门IOC和AOP学习笔记 概述 Spring框架的核心有两个: Spring容器作为超级大工厂,负责管理.创建所有的Java对象,这些Java对象被称为Bean. Spring容器管理容 ...

  5. Spring框架IOC,DI概念理解

    1.什么是框架? 框架是一种重复使用的解决方案,针对某个软件开发的问题提出的. Spring框架,它是一个大型的包含很多重复使用的某个领域的解决方案. Spring的理念:不要重复发明轮子. 2.Sp ...

  6. Spring-初识Spring框架-IOC控制反转(DI依赖注入)

    ---恢复内容开始--- IOC :控制反转 (DI:依赖注入)使用ioc模式开发 实体类必须有无参构造方法1.搭建Spring环境下载jarhttp://maven.springframework. ...

  7. Spring框架IOC容器和AOP解析

    主要分析点: 一.Spring开源框架的简介  二.Spring下IOC容器和DI(依赖注入Dependency injection) 三.Spring下面向切面编程(AOP)和事务管理配置  一.S ...

  8. spring框架--IOC容器,依赖注入

    思考: 1. 对象创建创建能否写死? 2. 对象创建细节 对象数量 action  多个   [维护成员变量] service 一个   [不需要维护公共变量] dao     一个   [不需要维护 ...

  9. 【Java框架型项目从入门到装逼】第一节 - Spring框架 IOC的丧心病狂解说

    大家好,好久不见,今天我们来一起学习一下关于Spring框架的IOC技术. 控制反转--Spring通过一种称作控制反转(IoC)的技术促进了松耦合.当应用了IoC,一个对象依赖的其它对象会通过被动的 ...

随机推荐

  1. Mac下开发ASP.NET Core应用,我用FineUICore!

    在 Mac 下开发 ASP.NET Core 2.0+ 应用,我用FineUICore! FineUICore:企业级 ASP.NET 控件库,10年持续更新,只为你来:http://fineui.c ...

  2. 类String 常用方法

    字符串当中的常用方法之比较相关的方法 public boolean equals (object obj):将此字符串与指定的对象进行比较(只有参数是字符串并且内容相同才会返回true) public ...

  3. Docker 核心技术之镜像

    镜像简介 镜像是一个Docker的可执行文件,其中包括运行应用程序所需的所有代码内容.依赖库.环境变量和配置文件等. 通过镜像可以创建一个或多个容器. 镜像搜索 - docker search 作用: ...

  4. Docker 概览

    什么是Docker Docker是开发,运行和部署应用程序的开放管理平台. 开发人员能利用docker 开发和运行应用程序 运维人员能利用docker 部署和管理应用程序 Docker 平台介绍 Do ...

  5. Windows 下使用 工具修改文件的 时间

    1. 下载工具 https://www.cr173.com/soft/12992.html 2. 使用工具修改即可 3. 忘记了东西处理挺方便的.  尤其是往前改日期的时候.

  6. mysql时间比较

    ' and ZXBZ ='Y' AND SQRQ >= '2017-04-28 00:00:00' AND SQRQ <= '2017-04-28 23:59:59'; ;

  7. 运行错误:Application Error - The connection to the server was unsuccessful

    在模拟器上上启动ionic4.6版本 打包成的android APK,启动了很久结果弹出这个问题: Application Error - The connection to the server w ...

  8. Vue.js 2.x笔记:基本语法(2)

    1. Vue实例及选项 1.1 创建Vue实例(new Vue instance) 每个Vue Application必须创建一个root Vue Instance. <script> v ...

  9. BZOJ3033太鼓达人——哈密顿回路/欧拉回路

    题目描述 七夕祭上,Vani牵着cl的手,在明亮的灯光和欢乐的气氛中愉快地穿行.这时,在前面忽然出现了一台太鼓达人机台,而在机台前坐着的是刚刚被精英队伍成员XLk.Poet_shy和lydrainbo ...

  10. [RPM,YUM]RHEL Centos mount local source / RHEL CentOS挂载本地源

    RHEL: 使用YUM安装Oracle必要软件包,将操作系统ISO文件“rhel-server-6.5-x86_64.iso”分别上传至两个节点主机“/root”目录,以root用户登录,执行以下命令 ...