spring专题系列之IOC的理解和分析

简介: 根据时间安排,今天主要是对spring中IOC的理解。对于IOC的理解可以从以下几个角度去分析。什么是IOC?如何使用案例来理解?IOC有哪几种实现方式?IOC的底层实现过程是什么?根据这几个角度,开始今天的故事,

1 什么是IOC?


对于IOC的理解,主要是停留在概念和几种注入的方式上,虽然知道其生命周期,但是对整个bean管理的宏观角度,理解的不够深刻。


IOC:**控制反转(Inversion of Control)容器,**是一种设计思想。意味着将你设计好的对象交给容器控制。


1.1 什么是依赖注入


这个概念的理解,我准备使用一个案例来表示。如果a类中包含了b类,就说明a类对b类产生了依赖。如一个人需要车,这就说人对车产生了依赖。

class User{ 
  Car car; 
  public User(){ 
    car=new Car(); 
  } 
}

上面这个案例,可以看到,在User类中,包含了Car类,也就说User类对Car类产生了依赖。


按照传统的方式,User类如果想要使用Car基本上就是在内部new一个新对象即可。但是这样做缺点很大,new的方式也就意味着User和Car产生了紧耦合。不利于大规模使用。于是使用了另外一种方式可以代替。那就是什么时候用到Car,从外部直接传递过来就好。这样的话,耦合性就大大降低了。再看下面这种形式是不是就好很多了。


class User{ 
  Car car; 
  public User(Car car){ 
    this.car=car; 
  } 
}

像这样的方式就是依赖注入,也就是把依赖Car注入到了User中。

1.2 什么是控制反转


有了上面依赖注入的概念,再立即控制反转就比较简单了。


  • 谁控制谁:传统方式User是在内部new,现在我们通过依赖注入的方式注入依赖对象Car。现在spring出现了,发明了IOC,IOC里面有一个容器,这些依赖对象全部交给容器去管理。也就是说这些依赖对象的控制权交给了容器。
  • 如何反转:传统方式User是主动去new,这种方式是正转。反转是由容器来帮忙创建及注入依赖对象;


2 依赖注入的几种形式


目前主要有五种注入方式:SET注入,构造器注入,静态工厂,实例工厂。

本文直接使用网上的基本案例来实现。比如UserService依赖UserDao。先把UserDao定义好了,接下来看如何实现注入的


public class UserDao {
 public String userLogin() {
  return "userLogin()方法";
 }
}

下面看几种依赖注入的几种实现方式。


2.1 set注入


第一步: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 id="userDao" class="com.xxx.demo.UserDao"></bean>
 <!-- setter注入 -->
 <bean id="userService" class="com.xxx.demo.UserService">
        <!--ref是对于外部bean对象引用,与被引用的bean对象的id保持一致-->
  <property name="userDao" ref="userDao"></property>
 </bean>
</beans>

第二步:set方式注入

public class UserService {
    //一定要提供属性的setter方法
 private UserDao userDao;
 public void userlogin() {
  String res=userDao.userLogin();
  System.out.println(res);
 }
 public void setUserDao(UserDao userDao) {
  this.userDao = userDao;
 }
}

这种方式简单易操作。


2.2 构造器注入


第一步: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 id="userDao" class="com.xxx.demo.UserDao"></bean>
 <!-- 构造器注入 -->
 <bean id="userServiceV2" class="com.xxx.demo.UserServiceV2">
  <constructor-arg index="0" ref="userDao"></constructor-arg>
  <constructor-arg index="1" value="印度三哥"></constructor-arg>
 </bean>
</beans>

第二步:构造器注入

public class UserServiceV2 {
 private UserDao userDao;
 private String name;
 public void userlogin() {
  String res=userDao.userLogin();
  System.out.println(res);
  System.out.println(name);
 }
 public UserServiceV2(UserDao userDao,String name) {
  super();
  this.userDao = userDao;
  this.name = name;
 }
}

2.3 静态工厂注入


第一步: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 id="userDao01" class="com.xxx.demo.StaticFactory" factory-method="createuserDao"></bean>
 <bean id="userService01" class="com.xxx.demo.UserService">
  <property name="userDao" ref="userDao01"></property>
 </bean>
</beans>

第二步:定义静态工厂

public class StaticFactory {
 public static UserDao createuserDao(){
  return new UserDao();
 }
}

第三步:静态工厂注入

public class UserService {
 private UserDao userDao;
 public void userlogin() {
  String res=userDao.userLogin();
  System.out.println(res);
 }
 public void setUserDao(UserDao userDao) {
  this.userDao = userDao;
 }
}

2.4 实例化工厂


第一步: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 id="instanceFactory" class="com.xxx.demo.InstanceFactory"></bean>
 <bean id="userDao3" factory-bean="instanceFactory" factory-method="createUserDao"></bean>
 <bean id="userService02" class="com.xxx.demo.UserService">
  <property name="userDao" ref="userDao3"></property>
 </bean>
</beans>

第二步:工厂注入

public class InstanceFactory {
 public UserDao createUserDao(){
  return new UserDao();
 }
}

以上就是几种常见的注入方式。在开发中比较常用。知道了IOC的概念和几种实现方式之后,下面主要探讨IOC的底层实现原理。


3 IOC底层实现过程


以上的几种注入方式,可能有个疑问,那就是bean是如何从xml,再到注入类中的呢?看下面这张图

v2-b5fecb6d4db052e1c308e64862db5373_1440w.jpg

Spring IOC容器初始化的核心过程主要有四个步骤(还有一些如:后置加载器,国际化,事件广播器等一些过程不展开):


  1. Bean定义的定位,Bean 可能定义在XML中,或者一个注解,或者其他形式。这些都被用Resource来定位,读取Resource获取BeanDefinition 注册到 Bean定义注册表中。


  1. 第一次向容器getBean操作会触发Bean的创建过程,实列化一个Bean时 ,根据BeanDefinition中类信息等实列化Bean。


  1. 将实列化的Bean放到单列Bean缓存内。


  1. 此后再次获取向容器getBean就会从缓存中获取。


这张图是核心的过程。这个过程是已经简化了,具体的实现方式要设计到bean的生命周期的管理。安排到下一章节了。 spring的核心内容就是aop和ioc,知道了这俩是如何实现的之后,就是核心bean管理的核心实现,最后对配置文件进行介绍。

相关文章
|
8月前
|
XML Java 测试技术
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
555 26
|
5月前
|
XML Java 数据格式
Spring IoC容器的设计与实现
Spring 是一个功能强大且模块化的 Java 开发框架,其核心架构围绕 IoC 容器、AOP、数据访问与集成、Web 层支持等展开。其中,`BeanFactory` 和 `ApplicationContext` 是 Spring 容器的核心组件,分别定位为基础容器和高级容器,前者提供轻量级的 Bean 管理,后者扩展了事件发布、国际化等功能。
|
4月前
|
负载均衡 Java API
基于 Spring Cloud 的微服务架构分析
Spring Cloud 是一个基于 Spring Boot 的微服务框架,提供全套分布式系统解决方案。它整合了 Netflix、Zookeeper 等成熟技术,通过简化配置和开发流程,支持服务发现(Eureka)、负载均衡(Ribbon)、断路器(Hystrix)、API网关(Zuul)、配置管理(Config)等功能。此外,Spring Cloud 还兼容 Nacos、Consul、Etcd 等注册中心,满足不同场景需求。其核心组件如 Feign 和 Stream,进一步增强了服务调用与消息处理能力,为开发者提供了一站式微服务开发工具包。
517 0
|
10月前
|
XML Java 数据格式
【SpringFramework】Spring IoC-基于XML的实现
本文主要讲解SpringFramework中IoC和DI相关概念,及基于XML的实现方式。
208 69
|
7月前
|
Java 容器 Spring
什么是Spring IOC 和DI ?
IOC : 控制翻转 , 它把传统上由程序代码直接操控的对象的调用权交给容 器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转 移,从程序代码本身转移到了外部容器。 DI : 依赖注入,在我们创建对象的过程中,把对象依赖的属性注入到我们的类中。
|
6月前
|
SQL 前端开发 Java
深入分析 Spring Boot 项目开发中的常见问题与解决方案
本文深入分析了Spring Boot项目开发中的常见问题与解决方案,涵盖视图路径冲突(Circular View Path)、ECharts图表数据异常及SQL唯一约束冲突等典型场景。通过实际案例剖析问题成因,并提供具体解决方法,如优化视图解析器配置、改进数据查询逻辑以及合理使用外键约束。同时复习了Spring MVC视图解析原理与数据库完整性知识,强调细节处理和数据验证的重要性,为开发者提供实用参考。
269 0
|
10月前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
10月前
|
Java Spring 容器
【SpringFramework】Spring IoC-基于注解的实现
本文主要记录基于Spring注解实现IoC容器和DI相关知识。
153 21
|
10月前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
246 12
|
10月前
|
XML Java 数据格式
Spring Core核心类库的功能与应用实践分析
【12月更文挑战第1天】大家好,今天我们来聊聊Spring Core这个强大的核心类库。Spring Core作为Spring框架的基础,提供了控制反转(IOC)和依赖注入(DI)等核心功能,以及企业级功能,如JNDI和定时任务等。通过本文,我们将从概述、功能点、背景、业务点、底层原理等多个方面深入剖析Spring Core,并通过多个Java示例展示其应用实践,同时指出对应实践的优缺点。
153 14