本文内容

  1. 简单回顾IoC和DI概念
  2. Spring容器的概念
  3. 的xml配置和初始化
  4. 容器的基本使用
  5. bean的定义和初始化配置

简单理解IoC和DI概念

什么是IoC控制反转?

通俗地但不严谨地讲,以前传统方式都是应用程序需要一个对象,直接通过new的方式来生成,该对象的管理也是由当前程序自己控制。现在有一个容器,负责将应用程序需要的所有对象都new好了,对象都统一由这个容器管理,应用程序需要对象的时候直接找容器要,应用程序说我不关系对象是怎么来的反正你给我就行。这样和以前的方式不一样了,以前是应用程序自己创建和管理,现在交给容器统一创建管理了,控制权发生反转了,这简单理解为IoC。

什么是DI依赖注入?

通俗地但不严谨地讲,应用程序需要的对象A依赖于B,由容器直接自动将B依赖给到对象A,可以理解为自动将依赖B注入到A 中了。

Spring官方的对于这个2个概念的说明,比较绕,这里也附上。

IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes or a mechanism such as the Service Locator pattern.

IoC也称为依赖项注入(DI)。在这个过程中,对象只能通过构造函数参数、工厂方法的参数或在对象实例被构造或从工厂方法返回后在对象实例上设置的属性来定义它们的依赖关系(即它们所处理的其他对象)。容器然后在创建bean时注入这些依赖项。这个过程本质上是bean本身的逆过程(因此得名“控制反转”),它通过直接构造类来控制依赖项的实例化或位置

Spring容器的概念和使用

Spring IoC容器负责实例化、配置和组装bean。容器通过读取配置元数据来获取关于实例化、配置和组装哪些对象的指令。配置元数据以XML、Java注释或Java代码表示。

Talk is cheap. Show me the code

屁话少说,放码过来

下面将通过一个案例来快速演示Spring容器的简单使用。

环境准备

IDE: IDEA

Maven: 3.5.6

JDK: java8

创建Maven工程并Spring引入依赖

pom文件如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId>
<artifactId>spring-ioc-quickstart</artifactId>
<version>1.0-SNAPSHOT</version> <properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<spring.verison>5.2.19.RELEASE</spring.verison>
</properties> <dependencies>
<!--Spring上下文的依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.verison}</version>
</dependency>
</dependencies> <build>
<!--配置文件相关-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.yml</include>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.yml</include>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>

创建2个简单类A、B

A依赖B如下

public class A {
private B b; public B getB() {
return b;
} public void setB(B b) {
this.b = b;
}
}

B如下

public class B {
}

创建Spring的XML配置文件

resources目录创建spring.xml配置文件,并配置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"> <!--A的定义信息-->
<bean id="a" class="com.crab.spring.A">
<!--注入B对象依赖-->
<property name="b" ref="b"/>
</bean> <!--B的定义信息-->
<bean id="b" class="com.crab.spring.B"></bean>
</beans>

创建一个测试类

public class MainTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
A a = context.getBean("a", A.class);
B b = context.getBean("b", B.class);
System.out.println("A对象:" + a);
System.out.println("A对象中的B依赖: " + a.getB() );
System.out.println("B对象:" + b);
}
}

最终文件目录结构

运行结果

对象AB都统一由ClassPathXmlApplicationContext容器管理,并在A需要B依赖的时候容器自动注入,应用程序需要的时候直接从容器拿接口如context.getBean(),。结合着里面下IoC和DI的概念。以上就是Spring容器的简单使用。

A对象:com.crab.spring.A@2d928643
A对象中的B依赖: com.crab.spring.B@5025a98f
B对象:com.crab.spring.B@5025a98f

Spring 容器对象

BeanFactory 接口

BeanFactory 接口提供了一种高级配置机制,能够管理任何类型的对象,是Spring IoC容器根接口。主要的定义方法如下。

package org.springframework.beans.factory;

public interface BeanFactory {
// 指定名称获取bean
Object getBean(String name) throws BeansException;
// 指定名称和类型获取bean
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
// 指定类型获取bean
<T> T getBean(Class<T> requiredType) throws BeansException;
// 容器中是否存在bean
boolean containsBean(String name);
// 是否是单例
boolean isSingleton(String name) throws NoSuchBeanDefinitionException; //
}

非常建议阅读BeanFactory 的源码上的注释说明,非常的详尽,常见的面试:请描述下Spring的生命周期?注释上就有非常官方的完整说明

ApplicationContext接口

ApplicationContext接口是BeanFactory的子接口,在其基础上提供更多企业级的功能。负责实例化、配置和组装bean,支持xml配置文件、java注解、Java-based等方式进行bean的配置。常使用的实现类有: ClassPathXmlApplicationContextFileSystemXmlApplicationContextAnnotationConfigApplicationContext等,后面详细讲解和使用,请保持阅读的热情。

bean定义对象

在 Spring 中,构成应用程序并由 Spring IoC 容器管理的对象称为 bean。这些 bean 是使用提供给容器的配置元数据创建的,如以 XML 定义的形式。

<!--A的定义信息-->
<bean id="a" class="com.crab.spring.A">
<!--注入B对象依赖-->
<property name="b" ref="b"/>
</bean>

xml中<bean />配置格式和支持元素如下:

<bean id="myChild" class="com.crab.spring.demo02.ChildBean"
init-method="init"
destroy-method="destroy"
name="childBean,aliasName"
parent="myParent"
scope="singleton"
primary="true"
depends-on="myParent"
autowire="byType"
autowire-candidate="true"
factory-bean="myFactory"
factory-method="getObj"
abstract="false"
></bean>
元素 说明
id 唯一ID
class 对应的类,全路径
name 支持名称,可以逗号/分号/空格来分隔多个,多个名称可用作别名
init-method 自定义的初始化方法
destroy-method 自定义的bean被销毁的方法
parent 指定父类引用
scope 指定作用域,如单例和原型,后面详细讲
primary 是否是主要的,用于依赖注入时候容器内有多个同类型的bean时做选择
depends-on 依赖于容器中的另外一个bean的引用
autowire 自动注入依赖,指定通过名称或是类型
autowire-candidate 标记自动依赖注入时候选
factory-bean 指定创建该bean的工厂
factory-method 指定创建的工厂方法
abstract 是否是抽象
lazy-init 延迟加载

通常情况下,如果不显式指定name ,Spring默认生成名称的规则是:将类名称转成小驼峰式来命名bean。如AccountManager 生成accountManager

在Spring容器内,bean的定义信息最终是通过接口BeanDefinition及其实现类体现。BeanDefinition接口和抽象类AbstractBeanDefinition`,主要定义如下

package org.springframework.beans.factory.config;

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

	void setParentName(@Nullable String parentName);
void setBeanClassName(@Nullable String beanClassName);
void setScope(@Nullable String scope);
void setLazyInit(boolean lazyInit);
void setDependsOn(@Nullable String... dependsOn);
void setAutowireCandidate(boolean autowireCandidate);
void setPrimary(boolean primary);
void setFactoryBeanName(@Nullable String factoryBeanName);
void setFactoryMethodName(@Nullable String factoryMethodName);
void setInitMethodName(@Nullable String initMethodName);
void setDestroyMethodName(@Nullable String destroyMethodName);
// 省略
}
package org.springframework.beans.factory.support;

public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable {
private volatile Object beanClass;
private String scope = SCOPE_DEFAULT;
private boolean abstractFlag = false;
private Boolean lazyInit;
private int autowireMode = AUTOWIRE_NO;
private String[] dependsOn;
private boolean autowireCandidate = true;
private boolean primary = false;
private String factoryBeanName;
private String factoryMethodName;
private String initMethodName;
private String destroyMethodName;
}

总结

本文主要讲解了Ioc的概念,演示Spring Ioc容器的快速使用,并详细说明bean定义元素。下一篇将讲bean的依赖注入。

本文对应的源码:

https://github.com/kongxubihai/pdf-spring-series/tree/main/spring-ioc-quickstart

知识分享,转载请注明出处。学无先后,达者为先!

Spring系列2:Spring容器基本概念和使用的更多相关文章

  1. Spring 系列教程之容器的功能

    Spring 系列教程之容器的功能 经过前面几章的分析,相信大家已经对 Spring 中的容器功能有了简单的了解,在前面的章节中我们一直以 BeanFacotry 接口以及它的默认实现类 XmlBea ...

  2. Spring系列之Spring常用注解总结 转载

    Spring系列之Spring常用注解总结   传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop.事物,这么做有两个缺点:1.如果所有的内容都配置在.xml文件中,那么.x ...

  3. Spring系列(七) Spring MVC 异常处理

    Servlet传统异常处理 Servlet规范规定了当web应用发生异常时必须能够指明, 并确定了该如何处理, 规定了错误信息应该包含的内容和展示页面的方式.(详细可以参考servlet规范文档) 处 ...

  4. Spring系列(零) Spring Framework 文档中文翻译

    Spring 框架文档(核心篇1和2) Version 5.1.3.RELEASE 最新的, 更新的笔记, 支持的版本和其他主题,独立的发布版本等, 是在Github Wiki 项目维护的. 总览 历 ...

  5. Spring系列之Spring常用注解总结

    传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop.事物,这么做有两个缺点:1.如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大:如果按需求分开.xml文件 ...

  6. Spring系列之IOC容器

    一.概述 IOC容器就是具有依赖注入功能的容器,IOC容器负责实例化.定位.配置应用程序中的对象及建立这些对象之间的依赖.应用程序无需直接在代码中new 相关的对象,应用程序由IOC容器进行组装.在S ...

  7. Spring系列(一) Spring的核心

    Spring 简介 Spring 是一个开源轻量级企业应用架构,目的是为了简化企业级应用开发.(1)Spring 框架可以帮我们管理对象的生命周期,帮助我们管理对象间的依赖关系,相互协作:(2)Spr ...

  8. Spring 系列之Spring常用注解总结

    传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop.实物,这么做有两个缺点: 1.如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大:如果按需求分开.xml文 ...

  9. Spring系列(六) Spring Web MVC 应用构建分析

    DispatcherServlet DispatcherServlet 是Spring MVC的前端控制器名称, 用户的请求到达这里进行集中处理, 在Spring MVC中, 它的作用是为不同请求匹配 ...

  10. 【Spring系列】Spring IoC

    前言 IoC其实有两种方式,一种是DI,而另一种是DL,即Dependency Lookup(依赖查找),前者是当前软件实体被动接受其依赖的其他组件被IOc容器注入,而后者是当前软件实体主动去某个服务 ...

随机推荐

  1. SWPUCTF_2019_login(格式字符串偏移bss段)

    题目的例行检查我就不放了,将程序放入ida中 很明显的值放入了bss段的格式字符串,所以我们动态调试一下程序 可以看到ebp这个地方0xffd0dd17-->0xffd0dd38-->0x ...

  2. UVA10079 Pizza Cutting 题解

    Content 求用 \(n\) 条直线最多能将平面分成多少块区域. 多组输入,以一个负数结束. 数据范围:\(0\leqslant n\leqslant 2.1\times 10^8\). Solu ...

  3. JAVA发送xml格式的接口请求

    /** * * @param urlStr 接口地址 * @param xmlInfo xml格式参数数据 * @return */ public static String sendMsgXml(S ...

  4. 【LeetCode】Integer to English Words 解题报告

    Integer to English Words [LeetCode] https://leetcode.com/problems/integer-to-english-words/ Total Ac ...

  5. 【九度OJ】题目1177:查找 解题报告

    [九度OJ]题目1177:查找 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1177 题目描述: 读入一组字符串(待操作的),再读入 ...

  6. 【LeetCode】732. My Calendar III解题报告

    [LeetCode]732. My Calendar III解题报告 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/problems/my-calendar ...

  7. 【LeetCode】701. Insert into a Binary Search Tree 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  8. 【安卓】AndroidStudio使用本地gradle进行build的配置

    1.修改setting使用local gradle2.将下载的gradle-6.7.1-all.zip放入E:/AndroidProject文件夹 修改gradle-wapper.propertie使 ...

  9. CS5213demoboard设计电路|DMI转VGA带II2S音频输出转接线|CS5213方案

    CS5213是台湾CAPSTONE瑞奇达推出的一款HDMI(高清多媒体接口)到VGA转换芯片. CS5213设计HDMI转VGA带II2S转接线产品特性: ◇将完整的HDMI信号转换为VGA输出◇支持 ...

  10. Java实习生常规技术面试题每日十题Java基础(六)

    目录 1.在Java语言,怎么理解goto. 2.请描述一下Java 5有哪些新特性? 3.Java 6新特性有哪些. 4.Java 7 新特性有哪些. 5.Java 8 新特性有哪些. 6.描述Ja ...