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

news2024/11/24 12:42:42

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.coloradmin.cn/o/2193775.html

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

相关文章

MySQL之复合查询与内外连接

目录 一、多表查询 二、自连接 三、子查询 四、合并查询 五、表的内连接和外连接 1、内连接 2、外连接 前面我们讲解的mysql表的查询都是对一张表进行查询&#xff0c;即数据的查询都是在某一时刻对一个表进行操作的。而在实际开发中&#xff0c;我们往往还需要对多个表…

05:(寄存器开发)定时器一

定时器 1、系统定时器SysTick1.1、SysTick中断的使用1.2、使用SysTick制作延迟函数 2、基本定时器2.1、基本定时器中断的使用2.2、使用基本定时器制作延时函数 1、系统定时器SysTick 1.1、SysTick中断的使用 ①SysTcik系统滴答定时器和片上外设定时器不同&#xff0c;它在CPU…

【c语言——指针详解(3)】

文章目录 一、字符指针变量二、数组指针变量1、 数组指针变量是什么&#xff1f;2、 数组指针变量怎么初始化 三、⼆维数组传参的本质四、函数指针变量1、函数指针变量的创建2、函数指针变量的使⽤3、两段有趣的代码1&#xff09;typedef 关键字2&#xff09;typedef和define的…

<<迷雾>> 第8章 学生时代的走马灯(3)--走马灯 示例电路

几个首尾相连的触发器使用同一个控制端&#xff0c;能同时触发 info::操作说明 鼠标单击开关切换开合状态 注: 其中 CP 为按钮开关, 每点击一次, Q 的输出前进一级 注: 第一个触发器的输出端 Q 需要先置入高电平. 如果重置了电路, 可外接电源先使第一个 Q 置入高电平. 另: 因为…

开源跨平台三维模型轻量化软件osgGISPlugins-2、如何编译

上一篇&#xff1a;开源跨平台三维模型轻量化软件osgGISPlugins-1、简介 1、编译前的准备&#xff1a;安装、配置vcpkg包管理器 1&#xff09;安装及国内镜像替换教程(Windows和Linux环境都有):vcpkg国内镜像源替换 2&#xff09;下载第三方依赖库(Readme文档中所给出的百度网…

DBCCompare_TreeView中的同步查找功能实现方案

引言 在应用程序中&#xff0c;数据的可视化和交互性至关重要。TreeView 控件作为一种层级数据展示工具&#xff0c;能够有效地展示复杂的数据结构。本文将重点探讨如何在 TreeView 中实现同步查找功能&#xff0c;使得使用人员在操作一个树形结构时&#xff0c;能够自动更新另…

2-114 基于matlab的CA模型

基于matlab的CA模型&#xff0c;Singer模型对单机动目标进行跟踪算法&#xff0c;具有10页实验文档。采用蒙特卡罗方法对一个二坐标雷达对一平面上运动的目标进行观测&#xff0c;得到跟踪滤波结果。程序已调通&#xff0c;可直接运行。 下载源程序请点链接&#xff1a;2-114 …

计算机网络面试题——第三篇

1. TCP超时重传机制是为了解决什么问题 因为TCP是一种面向连接的协议&#xff0c;需要保证数据可靠传输。而在数据传输过程中&#xff0c;由于网络阻塞、链路错误等原因&#xff0c;数据包可能会丢失或者延迟到达目的地。因此&#xff0c;若未在指定时间内收到对方的确认应答&…

【大语言模型-论文精读】谷歌-BERT:用于语言理解的预训练深度双向Transformers

【大语言模型-论文精读】谷歌-BERT&#xff1a;用于语言理解的预训练深度双向Transformers Note&#xff1a; 持续更新中&#xff0c;未完。。。 目录 文章目录 【大语言模型-论文精读】谷歌-BERT&#xff1a;用于语言理解的预训练深度双向Transformers目录1. 引言2. 简介 1. …

Linux文件上传下载与压缩解压

首先用yum命令执行 yum install -y lrzsz 下载lrzaz1.文件上传命令: rz(拖曳方式有时行有时不行的)在终端直接输入rz,直接弹出Windows系统的文件,自行找文件进行上传操作2.下载: sz命令(拖曳方式有时行有时不行的) 用法:sz 下载文件或文件路径 默认下载路径在Windows系统相应的…

自然语言处理问答系统

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

C++(11)——vector的具体实现

目录 1.函数的头文件 2.默认成员函数 2.1构造函数 2.1.1无参的构造函数 2.1.2支持迭代器的构造函数 2.1.3支持n个val的构造函数 2.2拷贝构造函数 2.2.1写法一&#xff08;传统写法&#xff09; 2.2.2写法二&#xff08;现代写法&#xff09; 2.3赋值运算符重载函数 2…

PGMP01-概述

1.项目集管理绩效域 2.项目集管理标准的目的 the purpose of the standard for program management 定义&#xff1a;为项目集管理原则、时间和活动提供指导。这些原则、实践和活动被公认为在大多时候适用于大多数项目集&#xff0c;并为项目集管理的良好实践提供了支持。 管理…

tldr命令介绍

tldr命令介绍 安装 TLDR使用 TLDR更新命令仓库 TLDR 是 “Too Long; Didn’t Read” 的缩写&#xff0c;在 Linux中是一个非常有用的工具&#xff0c;旨在为用户提供简洁的命令行工具或程序的使用说明&#xff0c;TLDR的目标是解决传统手册页信息过于繁杂的问题&#xff0c;通过…

独享动态IP是什么?它有什么独特优势吗?

在网络世界中&#xff0c;IP地址扮演着连接互联网的关键角色。随着互联网的发展&#xff0c;不同类型的IP地址也应运而生&#xff0c;其中独享动态ip作为一种新型IP地址&#xff0c;备受关注。本文将围绕它的定义及其独特优势展开探讨&#xff0c;以帮助读者更好地理解和利用这…

使用keras-tuner微调神经网络超参数

目录 随机搜索RandomSearch HyperBand 贝叶斯优化BayesianOptimization 附录 本文将介绍keras-tuner提供了三种神经网络超参数调优方法。它们分别是随机搜索RandomSearch、HyperBand和贝叶斯优化BayesianOptimization。 首先需要安装keras-tuner依赖库,安装命令如…

State of ChatGPT ---- ChatGPT的技术综述

声明&#xff1a;该文总结自AI菩萨Andrej Karpathy在youtube发布的演讲视频。 原视频连接&#xff1a;State of GPT | BRK216HFS 基础知识&#xff1a; Transformer原文带读与代码实现https://blog.csdn.net/m0_62716099/article/details/141289541?spm1001.2014.3001.5501 H…

【GT240X】【06】Linux文本编辑软件vim

目录 一、说明 二、什么是 vim&#xff1f; 三、vi/vim 的使用 3.1 命令模式 3.2 输入模式 3.3 底线命令模式 四、vi/vim 按键说明 4.1 一般模式可用的光标移动、复制粘贴、搜索替换等 4.2 一般模式切换到编辑模式的可用的按钮说明 4.3 一般模式切换到指令行模式的…

案例-博客页面简单实现

文章目录 本文内容只涉及前端1. 内容要求2. 画面展示初始化面演示视频 3. 注意事项4. 代码区js文件夹下的jquery.min.js内容登录代码列表页面创作页面 本文内容只涉及前端 1. 内容要求 登录页面实现博客列表页面实现博客创作页面实现 链接: 开源在线 Markdown 编辑器文本框可…

布草洗涤厂自动统计单据管理打包标签———未来之窗行业应用跨平台架构

一、布草洗涤厂打包标签 二、大酒店楼层送货单 三、独立三联单销售单 四、职员司机统计报表 五、开通方法 扫码开通