第②篇 Spring IoC——容器

news2024/11/24 11:30:55

Spring最成功的是其提出的理念,而不是技术本身。

概念

Spring所依赖的两个核心理念:

  • 一个是控制反转(IoC)。
  • 另一个是面向切面编程(Aspect Oriented Programming,AOP)。

IoC是Spring的核心,可以说Spring是一种基于IoC编程的框架。因为Spring Boot是基于注解的开发Spring IoC,所以这章我会使用全注解来讲解Spring IoC,为后续打下基础。

IoC是一种通过描述来创建或者获取对象的技术,而这个技术不是Spring甚至不是Java独有的。Java初学者更多的时候熟悉的是使用new关键字来创建对象,而Spring是通过描述来创建对象的。Spring Boot并不建议使用XML,而是通过注解的描述生成对象,所以本章主要是通过注解来介绍Spring IoC技术。

一个系统可以创建各种对象,并且这些对象都需要进行管理。此外我们应该注意到对象之间并不是孤立的,它们之间还可能存在依赖的关系。例如,一个班级是由多个老师和同学组成的,那么班级就依赖于多个老师和同学了。为此Spring IoC还提供了依赖注入的功能,使得我们能够通过描述来管理各个对象之间的关系。

为了描述上述的班级、同学和老师这3个对象关系,我们需要一个容器去管理它们和它们之间的关系。在Spring中把每一个需要管理的对象称为Spring Bean(简称Bean),而Spring管理这些Bean的容器,称为Spring IoC容器(或者简称IoC容器)。IoC容器需要具备两个基本的功能:

  • 通过描述管理Bean,包括定义、发布、获取和销毁Bean;
  • 通过描述完成Bean之间的依赖关系。

在使用IoC之前,需要对IoC容器有一个基本的认识。

IoC容器的两个接口——BeanFactory和ApplicationContext

IoC容器会把Spring所创建的Bean给装配进来进行管理,所以我们主要就和IoC容器打交道,那么我们首先就需要去了解IoC容器底层的内容。对于IoC容器来说,最重要的就是BeanFactory和ApplicationContext这两个接口的定义。由于容器很复杂,一般来说我们只需要知道这两个接口大概能够提供的功能即可,也就是要知道要干什么,无需过度深入理解IoC容器的内容。

IoC容器的底层接口是BeanFactory,它的源码如下:

package org.springframework.beans.factory;

import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;

public interface BeanFactory {

    String FACTORY_BEAN_PREFIX = "&";

    Object getBean(String name) throws BeansException;

    <T> T getBean(String name, Class<T> requiredType) throws BeansException;

    Object getBean(String name, Object... args) throws BeansException;

    <T> T getBean(Class<T> requiredType) throws BeansException;

    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

    <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);

    <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);

    boolean containsBean(String name);

    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

    @Nullable
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;

    @Nullable
    Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;

    String[] getAliases(String name);
}

前面我们论述了Spring IoC技术是一个容器技术,那么所有的容器都会实现这个接口,这样就可以使用这个接口的方法,从IoC容器中获取Bean的相关信息了。

这里我们主要先谈多个getBean()方法,这些方法都是从IoC容器中获取Bean的。

注意:我们可以看到存在以按名称(by name)查找Bean的,也存在按类型(by type)查找Bean的,请注意这个非常重要,后续遇到的问题和面试的问题都会集中在这里。

BeanFactory是底层接口,它的实现类很多,如图1所示。

图1
图1

 图1中,可以看到存在很多的IoC容器,但是它们都会遵守BeanFactory的规范,我们了解BeanFactory接口,就能使用IoC容器了。

不过我们需要讨论另外一个十分重要的接口,那就是ApplicationContext,从图1可以看到它是BeanFactory的子接口。它的重要性在于扩展了许多的接口,极大的增强了IoC容器的功能

图2

从图2,可见ApplicationContext扩展了消息国际化接口(MessageSource)、环境可配置接口(EnvironmentCapable)、应用事件发布接口(ApplicationEventPublisher)和资源模式解析接口(ResourcePatternResolver),所以它的功能会更为强大。

 在Spring Boot中,因为不推荐使用XML,所以我不再介绍XML相关的内容。这里我推荐使用的是AnnotationConfigApplicationContext进行实践,因为它是一个全注解的Spring IoC容器,和Spring Boot的环境几乎一致。

开发第一个IoC容器

开发容器首先需要有存到容器的东西,那就是bean,为了创建Bean,我们先创建一个角色类,代码很简单。

package com.ykzhen.articles2.po;

public class Role {

    private Long id;
    private String roleName;
    private String note;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }
}

这个代码很简单,相信不用我做任何的解释。之前,我谈过IoC容器是通过描述去创建Bean的,那么如何描述呢?一般来说可以使用传统的XML,也可以使用Java配置文件,因为Spring Boot推荐使用Java配置文件,按趋势XML使用不多了,所以我这里使用Java配置文件。先给出代码,如下。

package com.ykzhen.articles2.conf;

import com.ykzhen.articles2.po.Role;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

// @Configuration标明这个文件是一个配置文件
@Configuration
public class AppConfig {

    // 将方法返回的值装配到IoC容器中,并且该Bean的名称为“role”
    @Bean("role")
    public Role initRole() {
        var role = new Role();
        role.setId(1L);
        role.setRoleName("role_name_1");
        role.setNote("note_1");
        return role;
    }

}

主要到下面的两个注解:

@Configuration:表示这个类是一个Java配置文件,这样就可以描述如何创建IoC容器。

@Bean:注解标注在方法上,表示将方法返回的值,装配到IoC容器中。

有了上面这两个文件,我们开始创建Spring IoC容器,代码如下。

package com.ykzhen.articles2;

import com.ykzhen.articles2.conf.AppConfig;
import com.ykzhen.articles2.po.Role;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AppMain {
    public static void main(String[] args) {
        // 通过配置文件,创建IoC容器
        var ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        try {
            // 获取Bean
            var role = ctx.getBean(Role.class);
            System.out.println(role.getRoleName());
        } finally {
            // 关闭IoC容器
            ctx.close();
        }
    }
}

我们运行代码,可以得到如下结果:

15:22:23.611 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@1cd072a9
15:22:23.620 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
15:22:23.711 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
15:22:23.712 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
15:22:23.713 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
15:22:23.715 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
15:22:23.719 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'appConfig'
15:22:23.723 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'role'
role_name_1
15:22:23.751 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@1cd072a9, started on Thu Jan 12 15:22:23 CST 2023
 

可见我们测试成功了。

总结:

上面,我们完成了装配Bean到IoC容器中,然后从IoC容器中去获取Bean的过程,这也是IoC容器最基本的功能。

对于装配Bean到IoC容器,我们还需要去讲述扫描的方式,还有其他相关的内容,这是后续文章需要做的事情了。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JS入门到精通详解(1)

JavaScript概述(需要记)什么是javascript?是一门&#xff08;基于对象&#xff09;和&#xff08;事件驱动&#xff09;的&#xff08;脚本语言&#xff09;。js诞生于哪一年&#xff1f;哪个公司&#xff1f;谁&#xff1f;第一个名字叫什么&#xff1f;1995年 网景 布兰登 l…

【Python】type、isinstance、issubclass详解

type type方法有两种重载形式&#xff1a; type(o: object)&#xff1b;type(name: str, bases:Tuple[type, ...], dict:Mapping[str: Any], **kwds) 使用第一种重载形式的时候&#xff0c;传入一个【object】类型&#xff0c;返回一个【type】对象&#xff0c;通常与object…

解决使用element-plus时使用el-select-v2组件时,选中后无法移除focus的状态的方法。

我们可以使用element-ui-plus的el-select-v2的组件&#xff0c;实现复合搜索和下拉框的功能。 使用如下模块&#xff1a; <template><el-select-v2 v-model"value" filterable :options"options" placeholder"Please select"visibleCha…

爸妈记性变差怎么办?

记不住事的时候&#xff0c;我们总会自嘲“老了&#xff0c;脑子不好使了”。记忆力总是和年龄挂钩的&#xff0c;所以很多子女听到父母这样说&#xff0c;也不会放在心上。但有时&#xff0c;记性变差不一定因为年龄&#xff0c;还有可能是患病的前兆。当父母出现频繁忘事的情…

zerotier虚拟网络配置,局域网与外网如同局域网一样访问。

zerotier:可以搭建用于自己的虚拟网络&#xff0c;经过授权连接成功之后彼此都在同一网段&#xff0c;可以像在局域网一样互相访问。 1.创建zerotier账户 2.创建网络&#xff08;Create A Network&#xff09;并记住网络标识&#xff08;NETWORK ID&#xff09; 一、openwrt设…

中华财险进击数字化

本文来源 / 瞭望 中华联合财产保险股份有限公司&#xff08;下称中华财险&#xff09;&#xff0c;是一家 36 年的老牌国有保险公司&#xff0c;全国营业网点超过 2900 个。近年来&#xff0c;中华财险在业务高速发展的同时&#xff0c;从难啃的硬骨头下手&#xff0c;重构核心…

Unity 之 Addressable可寻址系统 -- 可寻址系统面板介绍 -- 入门(二)

可寻址系统面板介绍 -- 入门&#xff08;二&#xff09;一&#xff0c;可寻址系统目录介绍1.2 创建分组1.2 目录介绍二&#xff0c;可寻址系统设置介绍2.1 Profile - 配置文件2.2 Catalog - 目录2.3 Content Update - 内容更新2.4 Downloads - 下载2.5 Build - 构建2.6 Build a…

【数据结构】5.6 树和森林

文章目录5.6.1 树的存储结构&#xff08;不是二叉树&#xff09;双亲表示法孩子表示法结构定义双亲孩子法孩子兄弟法5.6.2 二叉树的转换树与二叉树的转换将树转换成二叉树将二叉树转换成树森林与二叉树的转换森林转换成二叉树二叉树转换成森林5.6.3 树和森林的遍历树的遍历森林…

Nginx简介

一、什么是Nginx?Nginx是一个高性能的HTTP和反向代理Web服务器&#xff0c;同时也提供IMAP/POP3/SMTP服务。Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3/SMTP&#xff09;代理服务器。Nginx的特点是&#xff1a;占有内存少&#xff0c;并发能…

JJWT实现令牌Token

登录实现方式 Session 详情&#xff1a; https://www.cnblogs.com/andy-zhou/p/5360107.html 会话的概念 会话就好比打电话&#xff0c;一次通话可以理解为一次会话。我们登录一个网站&#xff0c;在一个网站上不同的页面浏览&#xff0c;最后退出这个网站&#xff0c;也是…

【Java AWT 图形界面编程】Container 容器 ② ( Frame 窗口示例 | Panel 示例 | 窗口中文乱码处理 )

文章目录一、Frame 窗口示例二、Panel 示例三、窗口中文乱码处理一、Frame 窗口示例 首先 , 创建 Frame 实例对象 , 该对象就是 操作系统中应用软件的 窗口 ; // 1. 创建窗口 Frame frame new Frame("AWT 图形界面编程");Frame 是 Window 的子类 , public class F…

前端号外—2022年最受欢迎居然是它,Node.js危已

导读 | 2022年是艰难的一年&#xff0c;不仅有互联网的寒冬、还有新冠疫情的洗礼。但是似乎这一切都阻挡不了JavaScript的内卷&#xff0c;一年不长不短的时间中&#xff0c;JavaScript从创新、性能、功能等多维度深度进化&#xff0c;给前端带来了诸多惊喜。本文基于github上流…

仓库管理系统demo搭建指南

1、简介 1.1、案例简介 本文将介绍&#xff0c;如何搭建云进销存-仓库管理。 1.2、应用场景 云进销存-仓库管理应用分仓管理并提供灵活的库存计算方式及库存预警。 2、设置方法 2.1、表单搭建 1&#xff09;新建表单【商品管理】&#xff0c;字段设置如下&#xff1a; …

TensorFlow笔记之神经网络完成多分类任务

文章目录前言一、数据集调用二、Tensorflow1.x1.单隐藏层2.模型保存与调用三、Tensorflow2.x1.全连接层类2.keras建模总结前言 对TensorFlow笔记之单神经元完成多分类任务进行修改&#xff0c;在tf1.x与tf2.x中使用神经网络完成手写体数字识别多分类任务。 一、数据集调用 数…

10、Javaweb_Cookkie会话Session修改IDEA代码模板

修改IDEA代码模板 选择Setting... 找到要修改的代码模板&#xff0c;点击ok修改即可 使用模板创建方法 ,点击文件包,右键New选择文件类型 点击ok即可 创建完成 会话技术 1. 会话&#xff1a;一次会话中包含多次请求和响应。 * 一次会话&#xff1a;浏览器第一次给服务器资…

JAVA开发(web常见安全漏洞以及修复建议)

web安全常见漏洞修复建议&#xff1a;SQL注入规避 代码层最佳防御sql漏洞方案&#xff1a;使用预编译sql语句查询和绑定变量。&#xff08;1&#xff09;使用预编译语句&#xff0c;使用PDO需要注意不要将变量直接拼接到PDO语句中。所有的查询语句都使用数据库提供的参数化查询…

92、【树与二叉树】leetcode ——222. 完全二叉树的节点个数:普通二叉树求法+完全二叉树性质求法(C++版本)

题目描述 原题链接&#xff1a;222. 完全二叉树的节点个数 解题思路 1、普通二叉树节点个数求法 &#xff08;1&#xff09;迭代&#xff1a;层序遍历BFS 遍历一层获取一层结点 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode …

华为交换机、路由器设备批量配置端口方法步骤

华为交换机、路由器批量配置端口方法步骤 在现实工作中&#xff0c;如果要对多个端口做同样的配置&#xff0c;每个接口逐一进行相同的配置&#xff0c;很容易出错&#xff0c;而且造成大量重复工作。 配置端口组功能就可以解决这个问题啦。 你只需要将这些以太网接口加入同一…

HTML学习笔记(全)

HTML 文章目录HTML第一章——HTML 基础认识1. 1 基础补充1.1.1 网页组成1.1.2 代码如何转换成网页1.1.3 渲染引擎&#xff08;了解&#xff09;1.1.4 web 标准1.2 HTML 基础认知1. HTML的概念2. HTML页面固定结构3. **标签说明&#xff1a;**第二章——HTML基础语法2.1——注释…

国产linux操作系统——麒麟操作系统的来龙去脉

文章目录1、linux操作系统2、国产操作系统3、麒麟操作系统4、引用1、linux操作系统 目前市场主流的linux操作系统分类大致如此&#xff0c;国产操作系统的麒麟操作系统&#xff0c;底层比较杂&#xff0c;所以单独一类。 2、国产操作系统 排名日期截止到2022 这里提一下排名第…