SpringBoot基础(四):bean的多种加载方式

SpringBoot基础系列文章

SpringBoot基础(一):快速入门

SpringBoot基础(二):配置文件详解

SpringBoot基础(三):Logback日志

SpringBoot基础(四):bean的多种加载方式


目录

  • 一、xml配置文件
  • 二、注解定义bean
    • 1、使用AnnotationConfigApplicationContext对象加载
    • 2、加载本地类
    • 3、加载第三方jar类
  • 三、特殊方式
    • 1、使用FactroyBean接口
    • 3.2、注解导入XML格式配置的bean
    • 3.3、通过上下文ApplicationContext注册bean
  • 四、@Import注解注入bean
    • 1、@Import导入普通类
    • 2、@Import导入实现了ImportSelector接口的类
    • 3、@Import导入实现了ImportBeanDefinitionRegistrar接口的类
    • 4、@Import导入实现了BeanDefinitionRegistryPostProcessor接口的类

一、xml配置文件

配置文件spring-bean.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">
    <!--xml方式声明自己开发的bean-->
    <bean id="person" class="com.xc.entity.Person"/>
    <bean class="com.xc.entity.Person"/>
    <bean class="com.xc.entity.Person"/>

    <!--xml方式声明第三方开发的bean-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"/>
</beans>

加载xml

public class App {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-bean.xml");
        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }
    }
}

输出结果:

person
com.xc.entity.Person#0
com.xc.entity.Person#1
dataSource

二、注解定义bean

1、使用AnnotationConfigApplicationContext对象加载

public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            System.err.println(beanDefinitionName);
        }
    }
}
public class MyConfig {
}

  使用AnnotationConfigApplicationContext对象加载MyConfig,即使MyConfig类什么注解没有,也会被注册为bean。

2、加载本地类

  • 使用的注解@Component或其他衍生注解@Service@Controller@Repository
@Service
public class BookServiceImpl implements BookService {
}

3、加载第三方jar类

  由于我们无法在第三方提供的技术源代码中去添加上述4个注解,因此当你需要加载第三方开发的bean的时候可以使用@Component@Configuration都可以,一般引入第三方倾向于后者。

//@Component
@Configuration
public class DbConfig {
    @Bean
    public DruidDataSource dataSource(){
        return new DruidDataSource();
    }
    @Bean
    public Cat cat(){
    	Cat cat = new Cat();
    	cat.setDruidDataSource(dataSource());
    	return cat; 
    }
}
  • @Configuration(proxyBeanMethods = true):默认设置,使用了cglib动态代理,cat里的dataSource和@Bean创建的dataSource是同一个对象,可以理解为单例
  • @Configuration(proxyBeanMethods = false):此时和@Component注解功能一样,cat里的dataSource和@Bean创建的dataSource不是同一个对象,可以理解为多例
  • 如果配置中@Bean标识的方法之间不存在依赖调用的话,可以设置为false,可以避免拦截方法进行代理操作,提升性能

三、特殊方式

1、使用FactroyBean接口

  • spring提供了一个接口FactoryBean,也可以用于声明bean
  • 实现了FactoryBean接口的类造出来的对象不是当前类的对象,而是FactoryBean接口泛型指定类型的对象
  • 一般用来创建复杂对象
public class DogFactoryBean implements FactoryBean<Dog> {
    //创建bean的复杂过程
    @Override
    public Dog getObject() throws Exception {
        Dog d = new Dog();
        //.........
        return d;
    }
    //bean的类型
    @Override
    public Class<?> getObjectType() {
        return Dog.class;
    }
    //bean是否单例
    @Override
    public boolean isSingleton() {
        return true;
    }
}

配置类

public class MyConfig {
    @Bean
    public DogFactoryBean dog(){
        return new DogFactoryBean();
    }
}

启动类

public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
        System.out.println(context.getBean("dog"));
    }
}

3.2、注解导入XML格式配置的bean

  • 场景:旧项目xml配置bean融入配置类项目中
  • @ImportResource在配置类上直接写上要被融合的xml配置文件名即可
@Configuration
@ImportResource(locations = "spring-bean.xml")
public class SpringConfig {
}

3.3、通过上下文ApplicationContext注册bean

  • 在容器初始化完成后手动加载bean,创建方式很多

在这里插入图片描述

方式一:无参构造

public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        //上下文容器对象已经初始化完毕后,手工加载bean
        ctx.register(Mouse.class);
    }
}

方式二:多参构造

public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        //上下文容器对象已经初始化完毕后,手工加载bean
        ctx.registerBean("tom", Cat.class,"花猫",3);
    }
}

四、@Import注解注入bean

1、@Import导入普通类

  • 场景:将一个无任何注解的类加载为bean
  • 一个类@Improt只能用一次,想要导入多个使用{…,…}
  • 只有MyConfig加载为bean,@Import才生效
@Configuration
//@Import(Pig.class)
@Import({Dog.class,Cat.class})
public class MyConfig {
}
public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            System.err.println(beanDefinitionName);
        }
    }
}

输出结果:

myConfig
com.xc.springboot.bean.Dog
com.xc.springboot.bean.Cat

2、@Import导入实现了ImportSelector接口的类

  • 可以通过添加判断语句就可以实现对bean的加载控制
  • 返回值为多个全路径类名字符串
  • metadata为@Import注解类的元数据,可以拿到MyConfig类上所有的注解,注解里的属性,继承的接口,父类等等信息
  • 如下则是判断MyCofig类上有@Configuration注解则加载Dog类,否则加载Cat类
public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata metadata) {
        System.out.println("元数据Class名称:" + metadata.getClassName());
        //各种条件的判定,判定完毕后,决定是否装载指定的bean
        boolean flag = metadata.hasAnnotation("org.springframework.context.annotation.Configuration");
        if(flag){
            return new String[]{"com.xc.springboot.bean.Dog"};
        }
        return new String[]{"com.xc.springboot.bean.Cat"};
    }
}

配置类

@Configuration
@Import(MyImportSelector.class)
public class MyConfig {

}

启动类

public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            System.err.println(beanDefinitionName);
        }
    }
}

输出结果:

元数据Class名称:com.xc.springboot.bean.MyConfig
myConfig
com.xc.springboot.bean.Dog

3、@Import导入实现了ImportBeanDefinitionRegistrar接口的类

  • 返回值为void,通过Bean定义(beanDefinition)注册创建新的bean
  • 同样可以通过添加判断语句就可以实现bean的加载控制,更加细粒度判断bean
public class MyRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        BeanDefinition beanDefinition = 	
            BeanDefinitionBuilder.rootBeanDefinition(BookService.class).getBeanDefinition();
        registry.registerBeanDefinition("bookService",beanDefinition);
    }
}

4、@Import导入实现了BeanDefinitionRegistryPostProcessor接口的类

  • BeanDefinitionRegistryPostProcessor接口,其中有两个重要的方法:
    • postProcessBeanDefinitionRegistry:用于注册新的BeanDefinition
    • postProcessBeanFactory:用于在BeanFactory准备好后进行自定义操作
  • BeanDefinitionRegistryPostProcessor:bean定义注册最后的处理器(在以上处理后执行此操作),如果想bean最后确定一个值,可以在这里操作
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        // 通过 BeanDefinitionBuilder 创建一个新的 Bean 定义
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MyCustomBean.class);
        
        // 注册这个 bean 定义到 registry 中
        registry.registerBeanDefinition("myCustomBean", builder.getBeanDefinition());
        
        System.out.println("Bean definition registered: myCustomBean");
    }

    @Override
    public void postProcessBeanFactory(org.springframework.beans.factory.config.ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // 在这里可以对 BeanFactory 进行进一步的配置
        System.out.println("Bean factory post-processing");
    }
}

注意:所有通过@Import导入的bean名称为全路径名

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SCRM呼叫中心高保真Axure原型 源文件分享

在数字化时代&#xff0c;客户关系管理&#xff08;CRM&#xff09;对于企业的成功至关重要。SCRM呼叫中心后台作为一款专为CRM设计的软件原型&#xff0c;致力于为企业提供高效、智能的客户沟通解决方案。本文将详细介绍该产品的核心功能及其对企业提升客户满意度和销售业绩的…

C++,STL 030(24.10.14)

stack容器&#xff08;栈&#xff09;的基本概念&#xff1a; 1.stack容器是一种先进后出的数据结构&#xff0c;它只有一个出口。 2.图例&#xff1a; 注意&#xff1a; (1)进栈顺序&#xff1a;a1 -> a2 -> a3 -> a4 -> a5 (2)出栈顺序&#xff1a;a5 -> …

机器学习-决策树详解

决策树 决策树简介 学习目标 1.理解决策树算法的基本思想 2.知道构建决策树的步骤 【理解】决策树例子 决策树算法是一种监督学习算法&#xff0c;英文是Decision tree。 决策树思想的来源非常朴素&#xff0c;试想每个人的大脑都有类似于if-else这样的逻辑判断&#xff…

12.1-基础柱状图构建

Python基础综合案例——数据可视化 动态柱状图 通过Bar构建基础柱状图 反转x和y轴 调用 bar.reversal_axis() 我们现在所看到的数值是从下到上的&#xff0c;当我们反转之后数据是从左向右的&#xff0c;我们现在把数据放到柱的右边。即数值标签在右侧 添加y轴数据的时候&am…

oceanbase的日志量太大,撑爆磁盘,修改下日志级别

oceanbase的日志量太大&#xff0c;撑爆磁盘&#xff0c;修改下日志级别&#xff1a; [adminlnpg ~]$ obclient -h127.0.0.1 -uroot -P2881 -plinux123 Welcome to the OceanBase. Commands end with ; or \g. Your OceanBase connection id is 3221561020 Server version: O…

Android基于gradle task检查各个module之间资源文件冲突情况

做组件化开发的时候&#xff0c;我们经常会遇到各个不同的module之间资源文件冲突的问题&#xff0c;运行也不报错&#xff0c;但是会出现覆盖的问题&#xff0c;导致运行之后发送错误的效果。 所以我们需要利用一个gradlke 脚本task&#xff0c;来自动化检查资源文件冲突。 …

CST学习笔记(二)Floquet模式激励设置

CST学习笔记&#xff08;二&#xff09;Floquet模式激励设置 在CST中我们常常使用Floquet模式来仿真频率选择表面(FSS)或者超材料等&#xff0c;但是我们设置好Zmax的floquet模式数量后&#xff0c;启动仿真&#xff0c;会发现S参数一栏中有很多我们不想要看的S参数&#xff0…

OpenAI Canvas:提升编程与写作效率的全新工作界面

随着人工智能技术的飞速发展&#xff0c;大语言模型&#xff08;LLM&#xff09;不仅限于生成文本&#xff0c;还能逐步扩展至编程、设计等任务的支持。近期&#xff0c;OpenAI 推出了一个名为 Canvas 的全新功能&#xff0c;专门用于协助用户进行编程和写作。这一功能与 Claud…

【React】使用脚手架或Vite包两种方式创建react项目

1.使用脚手架搭建React项目&#xff1a; 在终端窗口运行如下命令即可&#xff1a; npx create-react-app react-basic(创建的文件目录) npx&#xff1a;Node.js工具命令&#xff0c;用于查找并执行后续的包命令。 2.使用Vite包创建React项目&#xff1a; 在终端窗口运行如…

【STM32 Blue Pill编程实例】-OLED显示DHT22传感器数据

OLED显示DHT22传感器数据 文章目录 OLED显示DHT22传感器数据1、DHT22介绍2、硬件准备与接线3、模块配置3.1 定时器配置3.2 DHT22引脚配置3.3 OLED配置4、代码实现在本文中,我们将介绍如何将 DHT22 温度和湿度传感器与 STM32 Blue Pill 开发板连接,并使用 HAL 库在 STM32CubeI…

学习底座架构-武汉

1 学习底座架构概述 大脑学习中心-边缘系统 一、当下教育现状 二、什么是学习底座 三、学习底座价值 七、学习底座解决问题的流程 案例&#xff1a;以4R注意力为例 一 注意力问题解决流程 二 注意力问题的危害 三 衡量注意力水平高低的标准 四 注意力问题4大根源 & 2大诱因…

掌握未来技能:亚马逊云科技推出生成式 AI 认证计划!

目录 前言 生成式 AI 的力量 1. 内容创造的无限可能 2. 数据增强和个性化 3. 提高生产力 4. 教育和研究的辅助工具 5. 突破语言障碍 关于亚马逊云科技生成式 AI 认证 1. 认证目标 2. 认证内容 3. 认证优势 如何获得认证 1. 在线学习 2. 实践考试 3.AWS Certifie…

无人机电机故障率骤降:创新设计与六西格玛方法论双赢

项目背景 TBR-100是消费级无人机头部企业推出的主打消费级无人机&#xff0c;凭借其出色的续航能力和卓越的操控性&#xff0c;在市场上获得了广泛认可。在产品运行过程&#xff0c;用户反馈电机故障率偏高&#xff0c;尤其是在飞行一段时间后出现电机过热、损坏以及运行不稳定…

基础入门-Web应用架构搭建漏洞HTTP数据包

网站搭建 这里给一个网站搭建的视频链接&#xff0c;之前又搞过搭建服务器&#xff0c;这里就不再重做了 https://www.bilibili.com/video/BV16A4y1X7vg/?spm_id_from333.337.search-card.all.click&vd_sourcec2c3c616b3ad1faf44a9f6f30a4dbb03 值得注意的是&#xff0c;…

P1320压缩技术(续集版

P1320压缩技术&#xff08;续集版 感觉这题还是蛮难的对我来说&#xff0c;通过这题我才知道原来字符串输入不碰到空格就会一起输进来 我参考了一写题解自己又写了自己的解法&#xff0c;vs中的scanf_s和scanf()用法不太一样&#xff0c;之前按scanf写法写一直在报错&#xff…

基于springboot+vue实现的酒店在线预订系统

基于springbootvue实现的酒店在线预订系统 &#xff08;源码L文ppt&#xff09;4-082 4.2 系统结构设计 构图是系统的体系结构&#xff0c;体系结构是体系结构体系的一部分&#xff0c;体系结构体系是体系结…

Chromium 中chrome.cookies扩展接口c++实现分析

chrome.cookies 使用 chrome.cookies API 查询和修改 Cookie&#xff0c;并在 Cookie 发生更改时收到通知。 更多参考官网定义&#xff1a;chrome.cookies | API | Chrome for Developers (google.cn) 本文以加载一个清理cookies功能扩展为例 https://github.com/Google…

全面讲解C++

数据类型 1.1 基本数据类型 1.1.1 整型&#xff08;Integer Types&#xff09; 整型用于表示整数值&#xff0c;分为以下几种类型&#xff1a; int&#xff1a;标准整数类型&#xff0c;通常为4字节&#xff08;32位&#xff09;。short&#xff1a;短整型&#xff0c;通常…

集合框架08:LinkedList源码分析、ArrayList和LinkedList区别

视频链接&#xff1a;13.15 LinkedList源码分析_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1zD4y1Q7Fw?spm_id_from333.788.videopod.episodes&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5&p15 13.16 ArrayList和LinkedList区别_哔哩哔哩_bilibilihttps://…

取证之FTK Imager学习笔记

一、FTK Imager制作镜像详细教程 1、文件-创建磁盘镜像 2、参数详解&#xff1a; 1&#xff09;物理驱动器 整个驱动器&#xff0c;如&#xff1a;识别到的是整块硬盘、U盘等&#xff0c;而不管你分几个分区&#xff1b; 2&#xff09;逻辑驱动器&#xff08;L&#xff09…