全注解下的SpringIoc

news2025/1/31 11:02:39

Spring架构中的核心理念就是IOC和AOP,可以说,Spring的强大离不开这两大特性。
因为spring boot推荐采用注解开发,所以文中主要介绍基于注解的Spring Ioc。

IoC容器简介

Spring IoC 容器是个管理 Bean(在Spring 中把每个需要管理的对象称为 Spring Bean ,简称 Bean ) 的容器,在Spring 定义中,它要求所有的 IoC 容器都需要实现接口 BeanFactory ,可以说,BeanFactory 是IoC容器的基础,下面看下这个接口的源码:
在这里插入图片描述
除了图中标记的这个方法之外,还有以下方法(由于篇幅,这里就直接copy出来了,感兴趣的小伙伴可以自己去查看源码)

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;
......

可以看到这个接口赋予了ioc容器可以使用bean的类型和名称来获取对应的bean。

由于 BeanFactory 的功能还不够强大,因此 Spring 在BeanFactory 的基础 还设计了 一个更为
高级的 接口ApplicationContext 。它是 BeanFactory 的子接口之一,在 Spring 的体系中 BeanFactory和
ApplicationContext 是最为重要的接口设计 ,在现实中我们使用的大部 Spring IoC 容器是
ApplicationContext 接口的实现类 ,它们的关系如图 所示
在这里插入图片描述
在图中可以看到, ApplicationContext 接口通过继承上级接口,进而继承 BeanFactory 接口, 但是在
BeanFactory 基础上,扩展了消息国际 化接口(MessageSource )、环境可配置接口EnvironmentCapable )、应用事件发布接口( ApplicationEventPublisher)和 资源模式解析接口(ResourcePatternResolver ),所以它的功能会更为强大。
以它的功能会更为强大。

基于注解的AnnotationConfigApplicationContext 容器基本使用

因为在Spring Boot 当中我们主要是通过注解来装配 Bean到 Spring IoC 容器中,所以这里主要介绍一个基于注解的 IoC 容器,它就是AnnotationConfigApplicationContext

首先我们创建一个User对象,准备将它交给Spring管理

@Data
public class BasicUser {
    private Long id;
    private String userName;
    private String note;
}

然后定义一个配置类,用来向Spring容器声明对象信息:

@Configuration
public class IocBasicAppConfig {
    @Bean(name = "basicUser")
    public BasicUser initUser() {
        BasicUser user = new BasicUser();
        user.setId(1L);
        user.setUserName("赵子明");
        user.setNote("这是一个普通用户");
        return user;
    }

这样Spring容器就可以知道我们声明的这个“basicUser”的bean了。
下面写一个测试类看一下:

@Slf4j
public class IocTest {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(IocBasicAppConfig.class);
        BasicUser user = context.getBean(BasicUser.class);
        log.warn(user.toString());
    }
}

可以看到代码中在创建容器时,指定了刚刚创建的配置类,“new AnnotationConfigApplicationContext(IocBasicAppConfig.class)”
然后运行main方法,可以如下日志被打印出来,说明成功从容器中拿到bean了
在这里插入图片描述

怎么装配自己的bean

上面的示例是容器的基本用法,但是如果有很多个bean需要交由容器管理,如果每个都用@Bean注解方式,那无疑是一件工作量很大的事情,所以spring这里提出了基于扫描机制来将bean交给容器管理。

扫描机制中的重要注解如下:
@ComponentScan 指定扫描规则
@Component 标记可以被扫描到的bean

查看@ComponentScan注解的源码可以发现,该注解支持许多扫描规则的配置,这里以指定扫描包和指定扫描时忽略不加入容器的配置举例。
先定义个配置类,用来配置扫描规则:

@ComponentScan(basePackages = {"com.zzm.iocscan"},
        excludeFilters = {@ComponentScan.Filter(classes = {Service.class, IocExclude.class})})
@Configuration
@Slf4j
public class ScanAppConfig {

    @Bean(value = "dataSource")
    public DataSource getDataSource(){
        Properties properties = new Properties();
        properties.setProperty("driver","com.mysql.jdbc.Driver");
        properties.setProperty("url","jdbc:mysql://zzm.zgj.cn:3306/ZzmSpringBootLearn");
        properties.setProperty("username","admin");
        properties.setProperty("password","admin");

        DataSource dataSource = null;
        try {
            dataSource = BasicDataSourceFactory.createDataSource(properties);
        }catch (Exception e){
            log.warn("创建数据源失败:", e);
        }
        return dataSource;
    }

}

这里我们指定了扫描的包是“com.zzm.iocscan”,并且被@Service和@IocExclude(自己定义的注解)这两个注解标记的bean会在扫描时忽略掉,不加入容器中。下面是相关的bean以及自定义注解@IocExclude

/**
 * @Author: 赵子明
 * @Date: 2023/4/5
 * @Description: IocExclude
 * @Version: ioc注入排除注解,被该注解标记的bean,将不会自动注入到ioc容器中
 */
public @interface IocExclude {
}

@Component("user")
@Data
public class ScanUser {
    @Value(value = "2")
    private Long id;

    @Value(value = "赵子明")
    private String userName;

    @Value(value = "这是通过component注解注入的bean")
    private String note;
}

@IocExclude
@Slf4j
public class UserIocExcludeService {

    public void printUser(ScanUser user){
        log.warn("UserIocExcludeService-printUser结果:【{}】",user.toString());
    }
}

@Service
@Slf4j
public class UserService {

    public void printUser(ScanUser user){
        log.warn("UserService-printUser结果:【{}】",user.toString());
    }
}

这几个类都放在“com.zzm.iocscan”包下面。按照我们配置的扫描规则,UserService 和UserIocExcludeService 这两个bean是不会加入到spring容器中的,而ScanUser 和dataSource则会被正常扫描;

下面创建一个测试类,代码如下:

@Slf4j
public class IocScanTest {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(ScanAppConfig.class);

        userTest(context);
        getDataSourceTest(context);
        userServiceTest(context);
        userIocExcludeServiceTest(context);
    }

    private static void userTest(ApplicationContext context){
        ScanUser user = context.getBean(ScanUser.class);
        log.warn(user.toString());
    }

    private static void userServiceTest(ApplicationContext context){
        UserService userService = context.getBean(UserService.class);
        userService.printUser(context.getBean(ScanUser.class));
    }

    private static void userIocExcludeServiceTest(ApplicationContext context){
        UserIocExcludeService userService = context.getBean(UserIocExcludeService.class);
        userService.printUser(context.getBean(ScanUser.class));
    }

    private static void getDataSourceTest(ApplicationContext context){
        DataSource dataSource = (DataSource) context.getBean("dataSource");
        log.warn("从ioc容器中获取到的数据源={}",dataSource.toString());
    }

运行main方法,得到日志如下:
在这里插入图片描述
可以看到ScanUser 和dataSource可以从容器中获取到,而UserService获取不到,因为UserService用了@Service注解标记,我们的扫描规则中设置了忽略被其标记的类。

下面将获取UserService的方法注释掉,继续运行main方法
在这里插入图片描述
可以看到UserIocExcludeService 这个也没有被扫描到容器中,因为UserIocExcludeService 用了@IocExclude注解标记,我们的扫描规则中设置了忽略被其标记的类。

可以有人想问,既然扫描机制这么方便,那为什么还用@Bean注解呢,因为有时候我们需要引入第三方的jar包,如上述的dataSource,此时就可以使用@Bean很方便的将其对象注入到Spring容器中了

@Bean(value = "dataSource")
    public DataSource getDataSource(){
        Properties properties = new Properties();
        properties.setProperty("driver","com.mysql.jdbc.Driver");
        properties.setProperty("url","jdbc:mysql://zzm.zgj.cn:3306/ZzmSpringBootLearn");
        properties.setProperty("username","admin");
        properties.setProperty("password","admin");

        DataSource dataSource = null;
        try {
            dataSource = BasicDataSourceFactory.createDataSource(properties);
        }catch (Exception e){
            log.warn("创建数据源失败:", e);
        }
        return dataSource;
    }

关于@ComponentScan注解的其他扫描规则的配置,感兴趣的小伙伴可以自行尝试下。

依赖注入的使用

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

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

相关文章

VMware vCenter Server 8.0U1 发布 - 集中式管理 vSphere 环境

请访问原文链接&#xff1a;VMware vCenter Server 8.0U1 - 集中式管理 vSphere 环境&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org 2023-04-18, VMware vSphere 8.0U1 发布。 详见&#xff1a;VMware vSphere 8 Update 1 新…

单片机的实例——28BYJ48步进电机

整体过程 准备资料1&#xff0c;步进电机内部结构示意图2&#xff0c;步进电机命名3&#xff0c;实际结构的转速比4&#xff0c;数值的含义5&#xff0c;实际内部主动轮结构分析实际内部机构及接线定子部分转子部分 定子和转子磁极的工作分析 6&#xff0c;工作时序7&#xff0…

机器学习 day06(向量化应用于多元线性回归的梯度下降算法,正规方程)

向量化多元线性回归&#xff0c;及梯度下降算法 将W₁&#xff0c;…&#xff0c;Wn写成向量W&#xff0c;将X₁&#xff0c;…&#xff0c;Xn写成向量X&#xff0c;而b还是之前的b注意&#xff1a;在多元线性回归的梯度下降算法中&#xff0c;Wj是指从W₁到Wn中的某一项&…

堆排序及top-k问题

堆排序及top-k问题 堆排序建堆向上调整建堆向下建堆 堆排序 top-k问题&#xff0c;建堆的应用 堆排序 堆排序&#xff0c;听名字就是要对堆进行排序&#xff0c;但当我们是无序数据时&#xff0c;首先我们就需要建立一个堆 建堆 这里让我们来回忆一下前面的堆&#xff0c;改…

Springboot基础学习之(二十三):实现定时任务

定时任务&#xff1a;在开发过程中是经常能够使用到的&#xff1a;定时发布邮件等等 先了解一下什么时cron表达式&#xff1f; 它是定义执行任务时间的一种时间表达式&#xff0c;使用方法 Scheduled(cron "0/2 * * * * ? ")&#xff0c;这里代码的含义是每两秒执行…

适用于 Windows 的 5 个最好的 PDF 转换器应用程序

由于稳定性、高分辨率、高安全性、易于传输等特点&#xff0c;PDF已经成为我们日常工作中最常用的格式。我们在享受PDF带来便利的同时&#xff0c;也发现PDF带来了一些不便&#xff0c;其中最大的问题就是PDF内容的编辑难度。同时&#xff0c;并不是所有的文件都是PDF格式的&am…

【redis】Redis为什么能抗住10万并发?

文章目录1. Redis简介2. 内存操作3. 丰富的对象类型4. 高效的数据结构5. 单线程模型6. 多路IO复用模型7. 总结1. Redis简介 Redis是一个开源的&#xff0c;基于内存的&#xff0c;高性能的键值型数据库。它支持多种数据结构&#xff0c;包含五种基本类型 String&#xff08;字…

搭建vue3项目+按需引入element-ui框架组件

场景&#xff1a;使用vue create脚手架快速搭建vue的项目 前提&#xff1a;需要安装node.js和cnpm以及yarn 并且cnpm需要设置为淘宝镜像&#xff0c;cnpm和yarn安装教程网上很多可以自行搜索 1.使用dos命令安装vue-cli脚手架 //这个是从镜像源下载 cnpm install -g vue/cli 查…

设计模式简述

设计模式(简述) 设计模式的分类 ​ 根据目的可以分为创建型、结构性和行为型三类&#xff1a; 创建型模型&#xff1a;创建对象结构性模型&#xff1a;处理类或对象的组合行为型模式&#xff1a;用于描述对类或对象怎样交互和怎么分派职责 ​ 根据范围可以分为类模式和对象…

13.基于双层优化的电动汽车日前-实时两阶段市场竞标

MATLAB代码&#xff1a;基于双层优化的电动汽车日前-实时两阶段市场竞标 关键词&#xff1a;日前-实时市场竞标 电动汽车 双层优化 编程语言&#xff1a;MATLAB平台 内容简介&#xff1a;代码主要做的是电动汽车充电站市场竞标策略&#xff0c;采用双层优化模型对电动汽车…

Redis缓存穿透、击穿、雪崩面试题详解

缓存穿透 问题&#xff1a; 指的是客户端请求的数据在缓存中找不到&#xff0c;数据库中也没有存储&#xff0c;客户端还不断的发起请求。这样每次都无法在数据库查询到&#xff0c;缓存中永远没有这个数据。 ​ 这样的话&#xff0c;客户端一直去访问&#xff0c;会给后端数据…

【观察】解读新一代戴尔AMD服务器:场景优化为先,筑牢数字化底座

毫无疑问&#xff0c;今天算力就是生产力已成为业界共识&#xff0c;特别是算力作为数字经济时代的关键生产力要素&#xff0c;更成为了挖掘数据要素价值&#xff0c;推动数字经济发展的核心支撑力和驱动力。 在此过程中&#xff0c;由算力驱动的数字经济除了以信息产业这一独立…

老胡的周刊(第087期)

老胡的信息周刊[1]&#xff0c;记录这周我看到的有价值的信息&#xff0c;主要针对计算机领域&#xff0c;内容主题极大程度被我个人喜好主导。这个项目核心目的在于记录让自己有印象的信息做一个留存以及共享。 &#x1f3af; 项目 Auto-GPT[2] Auto-GPT 是一个实验性的开源应…

极简sklearn-使用决策树预测泰坦尼克号幸存者

泰坦尼克号幸存者数据集是kaggle竞赛中入门级的数据集&#xff0c;今天我们就来用决策树来预测下哪些人会成为幸存者。 数据集下载地址: https://download.csdn.net/download/ting4937/87630361 数据集中包含两个csv文件&#xff0c;data为训练用数据,test为测试集。 探索数据…

通过HBuilderX运行uniapp到微信者开发工具

目录 一、安装开发工具 二、配置运行微信开发者工具 三、异常处理 1.[微信小程序开发者工具] ? Enable IDE Service (y/N) [27D[27C 2. [error] Error: Fail to open IDE 3.[app.json 文件内容错误] app.json: 在项目根目录未找到 app.json 一、安装开发工具 安装HBuil…

如今的就业环境下,怎样才能跻身于高收入的IC行业?

看到不少人失业找工作&#xff0c;其实现在不光是大学生难找工作&#xff0c;在职的人工作也不怎么开心。 要么累&#xff0c;要么没前途。 要么又累又没前途。 总的占个啥吧&#xff0c;现在大家面临的问题就是工作时间越来越久&#xff0c;人际关系也搞得很压抑&#xff0…

初识linux之线程同步与生产者消费者模型

目录 一、线程同步的概念 1. 饥饿状态 2. 同步的概念 二、生产者消费者模型 1. 生产者消费者模型基本概念 2. 生产者、消费者之间的关系 2.1 消费者与消费者的关系 2.2 生产者和生产者的关系 2.3 生产者和消费者的关系 3. “321”原则 4. 消费者与生产者模型的特点 …

C++数据结构:STL

数据结构和算法简介 数据结构 数据结构是相互间存在特定关系的数据的集合&#xff0c;分为逻辑结构和物理结构。 逻辑结构 反映数据元素之间的逻辑关系的数据结构&#xff0c;其中的逻辑关系是指数据元素之间的前后件关系&#xff0c;而与他们在计算机中的存储位置无关 集…

类加载器详解(重点)之双亲委派

回顾一下类加载过程 开始介绍类加载器和双亲委派模型之前&#xff0c;简单回顾一下类加载过程。 类加载过程&#xff1a;加载->连接->初始化。连接过程又可分为三步&#xff1a;验证->准备->解析。 加载是类加载过程的第一步&#xff0c;主要完成下面 3 件事情…

多线程基础

1.多线程基础概念 多线程&#xff1a;让程序同时做多件事情 多线程作用&#xff1a;提高效率 并发&#xff1a;在同一时间&#xff0c;有多个指令在单个cpu上交替执行 并行&#xff1a;在同一时刻&#xff0c;有多个指令在多个cpu上同时执行 2.多线程的实现 (1)继承Thread类…