进阶Spring(2)-BeanFactory和ApplicationContext实现

news2024/9/29 9:24:36

🏠个人主页:阿杰的博客
💪个人简介:大家好,我是阿杰,一个正在努力让自己变得更好的男人👨
目前状况🎉:24届毕业生,奋斗在找实习的路上🌟
🚗🚗为了让更多的人看到更优质的博客,阿杰正在努力的更新学习中心中的内容。

文章目录

  • 第二讲:BeanFactory和ApplicationContext实现
      • 总结:


第二讲:BeanFactory和ApplicationContext实现

首先看代码

ConfigurableApplicationContext context = SpringApplication.run(BeanfactoryimpApplication.class, args);

ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//class org.springframework.beans.factory.support.DefaultListableBeanFactory
System.out.println(beanFactory.getClass());

spring底层创建实体类就是依赖于DefaultListableBeanFactory。他是BeanFactory接口的一个主要实现类。

先创建类

package com.ajie.beanfactoryimp.newbean;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @author ajie
 * @version 1.0
 * @date 2023/5/2 15:56
 */
@Slf4j
public class Bean1 {
    public Bean1(){
        log.debug("构造 Bean1");
    }
    @Autowired
    private Bean2 bean2;
    public Bean2 getBean2(){
        return  bean2;
    }
}
package com.ajie.beanfactoryimp.newbean;

import lombok.extern.slf4j.Slf4j;

/**
 * @author ajie
 * @version 1.0
 * @date 2023/5/2 15:56
 */
@Slf4j
public class Bean2 {

    public Bean2(){
        log.debug("构造 Bean2");
    }
}
package com.ajie.beanfactoryimp.newbean;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author ajie
 * @version 1.0
 * @date 2023/5/2 15:55
 */
@Configuration
public class Config {
    @Bean
    public Bean1 bean1(){
        return  new Bean1();
    }


    @Bean
    public Bean2 bean2(){
        return  new Bean2();
    }
}

开始创建测试类

package com.ajie.beanfactoryimp.newbean;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigUtils;

/**
 * @author ajie
 * @version 1.0
 * @date 2023/5/2 15:52
 */
public class TestBeanFactory {
    public static void main(String[] args) {
        //spring底层创建实体类依赖这个类 DefaultListableBeanFactory
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        //定义名字为config的bean
        AbstractBeanDefinition beanDefinition =
                BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
        beanFactory.registerBeanDefinition("config",beanDefinition);

        //给BeanFactory 添加一些常用的后处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

        //BeanFactory的运行后处理器 可以解析@Configuration @Bean
        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        });

        for (String name : beanFactory.getBeanDefinitionNames()) {
            System.out.println(name);
        }

    }
}

可以看到@Bean被扫描 bean1 和bean2 被创建 @Configuration是用于spring类扫描的时候用的,加了这个注解的类被扫描到了就会被放进Bean工厂

image-20230502224658578

在加上这句代码

System.out.println(beanFactory.getBean(Bean1.class).getBean2());

会看到

image-20230502225630856

为什么呢? 因为beanFactory并没有解析@Autowired, @Resource…

加上

beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);

bean2就被创建出来了

image-20230502225854002

**注意: **

BeanFactory中的对象都是懒加载的,如果不去调用get()方法获取的话,就不会初始化,如果想要让对象在get()之前就创建好,需要调用beanFactory.preInstantiateSingletons()方法。

总结:

beanFactory 不会做的事

  • 不会主动调用BeanFactory的后处理器
  • 不会主动添加Bean的后处理器
  • 不会主动初始化单例
  • 不会解析BeanFactory,还不会解析 ${}, #{}

下面咱们在添加一点类

先定义一个接口Inter,再定义两个Bean,名称分别为Bean3和Bean4,都继承Inter,接着在Config中通过@Bean注解将Bean3和Bean4都加进Bean工厂中,然后在Bean1中定义一个Inter对象,通过@Autowired注解将实现类注入进来。

package com.ajie.beanfactoryimp.newbean;

/**
 * @author ajie
 * @version 1.0
 * @date 2023/5/2 23:07
 */
public interface Inter {
}

package com.ajie.beanfactoryimp.newbean;

import lombok.extern.slf4j.Slf4j;

/**
 * @author ajie
 * @version 1.0
 * @date 2023/5/2 23:08
 */
@Slf4j
public class Bean4 implements Inter{
    public Bean4() {
        log.debug("构造 bean4 ");
    }
}
package com.ajie.beanfactoryimp.newbean;

import lombok.extern.slf4j.Slf4j;

/**
 * @author ajie
 * @version 1.0
 * @date 2023/5/2 23:08
 */
@Slf4j
public class Bean3 implements Inter{
    public Bean3() {
        log.debug("构造 bean3 ");
    }
}

package com.ajie.beanfactoryimp.newbean;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author ajie
 * @version 1.0
 * @date 2023/5/2 15:55
 */
@Configuration
public class Config {
    @Bean
    public Bean1 bean1(){
        return  new Bean1();
    }
    
    @Bean
    public Bean2 bean2(){
        return  new Bean2();
    }
    
    @Bean
    public Bean3 bean3(){
        return  new Bean3();
    }
    @Bean
    public Bean4 bean4(){
        return  new Bean4();
    }
}

bean1 中添加

@Autowired
private Inter inter;
public Inter getInter(){
    return inter;
}

这是因为@Autowired 注解会先根据名字来匹配 没有的话 再根据类型来匹配 但是bean3和bean4都实现了inter所以会出现错误

image-20230502231937080

只需要吧inter改成 bean3就可以避免错误

如果我们在加上 @Resource(name=“bean4”)

这个时候他注册的是那个?

image-20230502232421663

运行后发现注册的是 bean3 ;

在beanFactory 加载后处理器的时候处理@Autowired注解的处理器internalAutowiredAnnotationProcessor比internalCommonAnnotationProcessor先进入,所以@Autowired会先被解析

image-20230502232747251

image-20230502232905229

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

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

相关文章

[Data structure]单链表常见算法题

⭐作者介绍:大二本科网络工程专业在读,持续学习Java,努力输出优质文章 ⭐作者主页:逐梦苍穹 ⭐所属专栏:数据结构。数据结构专栏主要是在讲解原理的基础上拿Java实现 ⭐如果觉得文章写的不错,欢迎点个关注一…

Hibernate(二)——Springboot整合Hibernate

在了解了Hibernate后&#xff0c;进一步将Hibernate和Springboot整合。 目录 引入依赖配置文件代码BeanDao层Service层Controller层 测试JpaRepository接口 引入依赖 <!--引入hibernate--> <dependency><groupId>org.springframework.boot</groupId>…

【大数据处理与可视化】四、数据预处理

【大数据处理与可视化】四、数据预处理 实验目的实验内容实验步骤一、案例——预处理部分地区信息1、导包2、读取文件3、检查并删除重复数据北京天津&#xff08;无重复数据&#xff09; 4、检查缺失值北京&#xff08;无缺失值&#xff09;天津&#xff08;向前填充&#xff0…

10分钟学会搭建sovits第一篇

So-vits-svc 基于端到端架构的VITS和soft-vc&#xff0c;用户只需准备几十分钟到几个小时不等的语音或歌声数据&#xff0c;就能制作&#xff08;训练&#xff09;属于自己的 AI 声库 &#xff08;前提是你的显卡足够给力&#xff09;&#xff0c;将一段语音或歌声转换为你想要…

简易时钟-QT学习

1 .h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPaintEvent> //绘制事件 #include <QPainter> //画家类 #include <QPaintDevice> #include <cmath> // #include <QPainterPath> #include <QTime> //时间类…

基于蜣螂算法的无人机航迹规划-附代码

基于蜣螂算法的无人机航迹规划 文章目录 基于蜣螂算法的无人机航迹规划1.蜣螂搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用蜣螂算法来优化无人机航迹规划。 1.蜣螂搜索算法 …

【LeetCode】646. 最长数对链

646. 最长数对链&#xff08;中等&#xff09; 思路 这道题和 300. 最长递增子序列 类似&#xff0c;我们可以定义 dp 数组&#xff0c;其中 dp[i] 表示以 i 结尾的子序列的性质。在处理好每个位置后&#xff0c;统计一遍各个位置的结果即可得到题目要求的结果。 但是题目中强…

ElasticSearch(二)简介

1. 简介 Elasticsearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎。 它能很方便的使大量数据具有搜索、分析和探索的能力。充分利用Elasticsearch的水平伸缩性&#xff0c;能使数据在生产环境变得更有价值。 Elasticsearch 的实现原理主要分为以下几个步骤&#xf…

Servlet执行原理和API详解

一、HttpServlet 我们写 Servlet 代码的时候, 首先第⼀步就是先创建类, 继承⾃ HttpServlet, 并重写其中的某些方法. 1.1核心方法 1.2处理GET或POST请求 1.3数据的两种提交方式 数据提交有两种方式&#xff1a; form 表单提交ajax 提交 1.3.1form 表单提交 form表单提交的…

瑞萨e2studio(24)----电容触摸配置(1)

瑞萨e2studio.20--电容触摸配置1 概述硬件准备新建工程工程模板保存工程路径芯片配置工程模板选择时钟配置添加TOUCH驱动配置CapTouch开启调优界面启动 CapTouch 调优通过电容触摸点亮LED 概述 这篇文档将创建一个使用 e2 studio 集成 QE 的电容式触摸应用示例&#xff0c;通…

C语言函数大全-- s 开头的函数(3)

C语言函数大全 本篇介绍C语言函数大全-- s 开头的函数&#xff08;3&#xff09; 1. sleep 1.1 函数说明 函数声明函数功能unsigned int sleep(unsigned int seconds);它是 C 语言标准库中的函数&#xff0c;用于使当前进程挂起一定的时间。在挂起期间&#xff0c;操作系统…

移动宽带安装说明一(刘欣)

2023年&#xff0c;五一假期给老家和父母家安装了2次宽带&#xff0c;记录一下吧。 一、移动光改覆盖率已经很高了 从当初的铁通“FTTB”覆盖小区,网线入户的带宽只能达到100M&#xff0c;提升到现在大面积的光改完成&#xff0c;普遍是光猫&#xff08;光纤MODEL&#xff09…

网络协议与攻击模拟-04-实施ARP攻击与欺骗

实施 ARP 欺骗和攻击 一、环境 1、 kali Linux 安装一个 arpspoof 2、win10 被攻击主机 二、 kaili 配置 kali Linux 系统是基于 debian Linux 系统&#xff0c;采用 deb 包管理方式&#xff0c;可以使用 apt 的方式进行直接从源安装 1、配置源 # 官方源 # deb http:/…

FastAPI如何区分多环境:开发/测试/预发布/生产环境

1 缘起 开始用FastAPI开发项目&#xff0c; 区分环境是部署的第一步&#xff0c;因此&#xff0c;需要区分dev/test/pre/prod等环境&#xff0c; 而FastAPI刚好提供了读取环境配置文件的参数&#xff0c;可以在启动服务时指定环境配置文件的路径&#xff0c; 参数为env_file&a…

【前端技术】Vue3 01:初识 Vue.js

Vue 可以说是非常流行了&#xff0c;至少在国内是这样&#xff0c;他是个轻量级的 JavaScript 框架&#xff0c;非常适合构建大型和中小型的 Web 应用程序&#xff0c;如果想和前端打交道&#xff0c;应该绕不过这个框架吧。 目录 1 Vue.js 介绍 2 IDE 选择 2.1 vscode 2.…

libfacedetection 人脸检测库的基本使用

目录 1、源码下载 2、编译 3、构建工程 4、个人总结 运行总结&#xff1a; 与CascadeClassifier级联分类器 人脸检测 对比: 1、源码下载 直接从github上克隆项目仓库。 git clone https://github.com/ShiqiYu/libfacedetection.git2、编译 这个项目使用了cmake脚本&#…

【LeetCode】413. 等差数列划分

413. 等差数列划分&#xff08;中等&#xff09; 思路 由于题目求的是等差数列 &#xff0c;很自然想到子数组一定满足 nums[i] - nums[i-1] nums[i-1] -nums[i-2]; 。然而我们对于 dp 数组的定义通常是以 i 结尾&#xff0c;满足某些条件的子数组数量&#xff0c;而等差数组可…

【LeetCode】300. 最长递增子序列

300. 最长递增子序列&#xff08;中等&#xff09; 方法一&#xff1a;动态规划 思路 通常来说&#xff0c;子序列不要求连续&#xff0c;而子数组或子字符串必须连续&#xff1b;对于子序列问题&#xff0c;第一种动态规划方法是&#xff0c;定义 dp 数组&#xff0c;其中 dp[…

PHP语言基础

&#x1f331;博客主页&#xff1a;大寄一场. &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 目录 前言 一、变量和数据类型 二、运算符和表达式 三、条件语句 四、循环语句 前言 PHP是一种非常流行的开源服务器端脚本语言&#xff0c;广泛用于Web开发…

Python sys模块

sys:使用或维护解释器 版本信息 Python版本 >>> sys.version 3.10.3 (tags/v3.10.3:a342a49, Mar 16 2022, 13:07:40) [MSC v.1929 64 bit (AMD64)]系统版本 >>> sys.platform win32 >>> 解释器版本 >>> sys.hexversion 50988016 >&g…