【Spring】使用@Bean和@Import注解配置Bean,与Bean的实例化

目录

1、bean是什么

2、配置bean

2.1、使用@Bean注解配置Bean

2.2、使用@Import注解配置Bean

 3、实例化Bean

1、bean是什么

        在 Spring 中,Bean 是指由 Spring 容器管理的对象。Spring IOC 容器负责创建、配置和管理这些 Bean 对象的生命周期。Spring IOC 容器会管理应用程序中的组件,并通过依赖注入(DI)将它们组装在一起。Bean 是应用程序的核心构建块,它们通常代表应用程序中的各种对象,例如服务、数据访问对象(DAO)、控制器等。

        要在 Spring 中使用 Bean,通常需要在 Spring 配置文件(如 XML 文件)或使用注解(@Component)来声明 Bean,并告诉 Spring 容器如何创建和配置它们。一旦 Bean 被声明和配置好,Spring 容器将负责实例化它们,并在需要时将它们注入到其他 Bean 中。

        简单来说就是:在 Spring 中,构成应用程序主干并由 Spring IoC 容器管理的对象称为 bean。bean 是由Spring IoC 容器实例化、组装和管理的对象。

 

2、配置bean

        配置bean可以通过在 xml 文件中用 <bean class=""> 这个标签的方式来进行显式的声明,但是这种方式太麻烦了。

        所以现在都是通过 @component注解 来把类配置成bean,在类级别上使用 @Component 注解或其派生注解(@Service、@Repository、@Controller 等)就可以将一个类声明为 Bean

        这两种配置方式可以看这一篇:【Spring】分别基于XML、注解和配置类实现Spring的IOC(控制反转)-CSDN博客

这里主要是使用@Bean和@Import注解配置Bean

2.1、使用@Bean注解配置Bean

@Bean 特性:

一、是放在方法上面的

二、必须放在配置类里面

        @Bean方法调用另外一个@Bean方法,会从spring容器中去获取

三、@Bean可以干预bean的实例化过程的,而且jar包中的类如果要配置bean就需要用@Bean

四、在这个方法中声明的参数,spring也会帮我们自动注入进来

相关代码:

//接口IUserDao
public interface IUserDao {
    //执行查询用户
    void getUser();
}


//接口IUserDao的实现类UserDao
public class UserDao implements IUserDao {
    @Override
    //执行查询用户
    public void getUser() {
        System.out.println("Holle Spring");
    }
}


//接口IUserService
public interface IUserService {
    void getUser();
}


//接口IUserService的实现类UserService
//@Service
public class UserService implements IUserService {

    @Autowired
    IUserDao userDao;
    @Override
    public void getUser() {
        userDao.getUser();
    }
}


//配置类SpringConfig
@Configuration
public class SpringConfig {

    @Bean  //使用@Bean配置UserService成为bean
    public IUserService userService(){
        IUserDao userDao = UserDao();
        UserService userService = new UserService();
        return userService;
    }

    @Bean  //使用@Bean配置UserDao成为bean
    public IUserDao UserDao(){
        return new UserDao();
    }
}


//测试类C3IocApplicationTests
@SpringBootTest
class C3IocApplicationTests {
    @Autowired
    IUserService userService;

    @Test
    void contextLoads() {
        userService.getUser();
    }
}

2.2、使用@Import注解配置Bean

@lmport 特性:

一、@lmport必须写在类上面,不能用于方法等其他的上面

二、标记的类必须是一个bean,否则不会起作用

 @lmport的三种使用方式

(1)普通类:就是直接@lmport(UserService.class)普通类,就会把这个普通类注入spring

示例:

(2)lmportSelector :用于根据完整限定名字符串批量注入Bean

        a、定义一个类实现lmportSelector

        b、批量注册bean(通过实现selectlmports,返回bean的完整类路径字符串数组)

        c、然后在配置类上加上@lmport(实现lmportSelector.class)

示例:

 

其他代码和上面使用@Bean的例子是一样的,实现了 ImportSelector 接口的 MyImportSelector 类代码:

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{
            "com.lt.ioc.service.UserService",
            "com.lt.ioc.dao.UserDao"
        };
    }
}

(3)ImportBeanDefinitionRegistrar

        定义一个类实现lmportBeanDefinitionRegistrar,然后在方法里根据beanDefinition注册bean

示例:和上面的 lmportSelector 用法一样,把实现了 ImportBeanDefinitionRegistrar 接口的类传递给@Import注解就可以

实现了 ImportBeanDefinitionRegistrar 接口的 MyImportBeanDefinitionRegistrar 类代码:

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
        //创建BeanDefinition,只有这个类的BeanDefinition存在了,才能根据这个BeanDefinition去创建类的bean对象
        RootBeanDefinition definition = new RootBeanDefinition();
        //把要创建bean的类的完整限定名传递给BeanDefinition
        definition.setBeanClassName("com.lt.ioc.service.UserService");
        //注册这个BeanDefinition
        registry.registerBeanDefinition("userService",definition);
    }
}

 3、实例化Bean

1、spring会默认使用无参构造器(无参构造函数)实例化

  • 有多个构造函数依然会调用无参构造函数
  • 如果只有一个有参构造函数,spring就会调用这个有参构造函数,并且把参数自动装配进来
  • 如果有参构造函数有个多个,并且没有无参构造函数,那就会报错,因为spring不知道该选哪一个构造函数,这时候对spring来说,他需要一个默认的无参构造函数

2、使用实例工厂方法实例化--@Bean

  • 可以自由的选择构造函数进行实例化

 

3、使用工厂Bean。实例化--FactoryBean

  • FactoryBean是一个接口
  • 需要有一个Bean,一旦这个Bean实现FaétoryBean就成为了特殊的Bean
  • 需要实现2个方法

        1)getObject() ---->当通过Bean实际名称获取到的就是getObject 返回的对象(伪装)

        2)getObjecType()---->想通过容器去获取对应(getObject 返回的对象)的类型,就需要返回getObject 返回的对象的类型

  • 可以自由的选择构造函数进行实例化

示例:

OrderService类是加了@Service注解并且实现了FactoryBean接口的一个类,代码:

@Service
public class OrderService implements FactoryBean {
    // 加了@Service注解并且实现了FactoryBean接口的OrderService变成了一个特殊的bean
    // 特殊: 就是根据bean(这里是OrderService)的名字实际上是获取getObject方法返回的对象(狸猫换太子)
    @Override
    public Object getObject() throws Exception {//(这里getObject方法中返回的对象就是UserService)
        return new UserService();
    }

    @Override
    public Class<?> getObjectType() {//想通过容器去获取对应(getObject 返回的对象)的类型,就需要返回getObject返回的对象的类型
        return UserService.class;
    }
}

获取容器,并分别通过FactoryBean接口中的两种方法从容器中获取UserService的bean和获取实现了FactoryBean接口的OrderService实际的Bean

//启动类C3IocApplication
@SpringBootApplication
public class IocApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext ioc = SpringApplication.run(IocApplication.class, args);

        //OrderService是加了@Service注解并且实现了FactoryBean接口的一个类,他是一个特殊的bean
        System.out.println(ioc.getBean("orderService"));//通过OrderService中重写了的getObject()方法来获取UserService的bean
        System.out.println(ioc.getBean(UserService.class));//通过OrderService中重写了的getObjectType()方法来获取UserService的bean
        //如果想获取FactoryBean实际的Bean可以 1.通过类型; 2.在beanName前加上&
        System.out.println(ioc.getBean(OrderService.class));
        System.out.println(ioc.getBean("&orderService"));
    }

}

推荐: 

【Spring】分别基于XML、注解和配置类实现Spring的IOC(控制反转)-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/137237805?spm=1001.2014.3001.5501

 【java多线程】通过等待唤醒机制、局部变量、原子变量实现线程同步-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/137122461?spm=1001.2014.3001.5501

【java多线程】通过等待唤醒机制、局部变量、原子变量实现线程同步-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/137122461?spm=1001.2014.3001.5501

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

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

相关文章

网络基础二——传输层协议UDP与TCP

九、传输层协议 ​ 传输层协议有UDP协议、TCP协议等&#xff1b; ​ 两个远端机器通过使用"源IP"&#xff0c;“源端口号”&#xff0c;“目的IP”&#xff0c;“目的端口号”&#xff0c;"协议号"来标识一次通信&#xff1b; 9.1端口号的划分 ​ 0-10…

Spring Boot中前端通过请求接口下载后端存放的Excel模板

导出工具类 package com.yutu.garden.utils;import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import org.apache.commons.io.IOUtils; import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.slf4j.Logger;…

06-编辑器

gedit编辑器 gedit是Ubuntu系统自带的编辑器&#xff0c;可以用来轻度编辑和记录一些内容。 在终端中我们通过以下命令打开&#xff1a; gedit 要打开或者新建的文件名虽然Ubuntu的图形界面也能通过gedit打开文件&#xff0c;但是用终端打开gedit可以动用更高的权限&#xff…

OpenHarmony实战开发-使用一次开发多端部署实现一多设置典型页面

介绍 本示例展示了设置应用的典型页面&#xff0c;其在小窗口和大窗口有不同的显示效果&#xff0c;体现一次开发、多端部署的能力。 1.本示例使用一次开发多端部署中介绍的自适应布局能力和响应式布局能力进行多设备&#xff08;或多窗口尺寸&#xff09;适配&#xff0c;保…

掌握机器学习新星:使用Python和Scikit-Learn进行图像识别

正文&#xff1a; 随着智能手机和社交媒体的普及&#xff0c;图像数据的生成速度比以往任何时候都快。为了自动化处理这些数据&#xff0c;我们需要强大的图像识别系统。机器学习提供了一种有效的方法来识别和分类图像中的对象。Scikit-Learn是一个流行的Python库&#xff0c;它…

谷粒商城实战(010 缓存-解决数据一致性问题以及SpringCache的使用)

Java项目《谷粒商城》架构师级Java项目实战&#xff0c;对标阿里P6-P7&#xff0c;全网最强 总时长 104:45:00 共408P 此文章包含第166p-第p172的内容 缓存一致性问题解决 redisson使用lua脚本&#xff0c;所以的锁都保证了原子性 改之前的代码 锁的粒度越小越好 如11号…

PS入门|黑白色的图标怎么抠成透明背景

前言 抠图可以算是PS的入门必备操作&#xff0c;开始学习PS的小伙伴可以根据本帖子推荐一步步学习哦&#xff01;但切勿心急&#xff5e; 今天给小伙伴们带来&#xff1a;黑白色的图标抠图教程 抠图有很多种方法&#xff0c;但根据类型的不同&#xff0c;使用适当的方法很重…

Redis底层数据结构-Dict

1. Dict基本结构 Redis的键与值的映射关系是通过Dict来实现的。 Dict是由三部分组成&#xff0c;分别是哈希表&#xff08;DictHashTable&#xff09;&#xff0c;哈希节点&#xff08;DictEntry&#xff09;&#xff0c;字典&#xff08;Dict&#xff09; 哈希表结构如下图所…

YUNBEE云贝-2024年4月PostgreSQL PGCM认证实战培训

课程介绍 了解关注开源技术&#xff0c;学习PG以点带面 Linux/Andriod&#xff08;操作系统&#xff09;、Apache/Tomcat&#xff08;应用服务器&#xff09;、OpenStack/KVM&#xff08;虚拟化&#xff09;、Docker/K8S&#xff08;容器化&#xff09;、Hadoop&#xff08;大…

利用Python和Selenium实现定时任务爬虫

网络爬虫在信息获取、数据分析等领域发挥着重要作用&#xff0c;而定时爬虫则可以实现定期获取网站数据的功能&#xff0c;为用户提供持续更新的信息。在Python中&#xff0c;结合Selenium技术可以实现定时爬虫的功能&#xff0c;但如何设置和优化定时爬虫的执行时间是一个关键…

C语言编写Linux的Shell外壳

目录 一、输出命令行 1.1 了解环境变量 1.2 获取用户名、主机名、当前路径 1.3 缓冲区改进MakeCommandLine 二、获取用户命令 2.1 读取函数的选择 2.2 细节优化 2.3 返回值 三、指令和选项分割 3.1 strtok 函数 3.2 分割实现 四、执行命令 4.1 fork 方法 4.2 进…

Qt C++ | Qt 元对象系统、信号和槽及事件(第一集)

01 元对象系统 一、元对象系统基本概念 1、Qt 的元对象系统提供的功能有:对象间通信的信号和槽机制、运行时类型信息和动态属性系统等。 2、元对象系统是 Qt 对原有的 C++进行的一些扩展,主要是为实现信号和槽机制而引入的, 信号和槽机制是 Qt 的核心特征。 3、要使用元…

蓝桥杯嵌入式学习笔记(9):RTC程序设计

目录 前言 1. RTC介绍 2. 使用CubeMx进行源工程配置 3. 代码编程 3.1 准备工作 3.2 进行bsp_rtc.h编写 3.3 进行bsp_rtc.c编写 3.4 main.c编写 3.4.1 头文件引用 3.4.2 变量声明 3.4.3 子函数声明 3.4.4 函数实现 3.4.5 main函数编写 4. 代码实验 5. 总结 前言 因本人备赛蓝…

2024年购买阿里云服务器多少钱?100元-5000元预算

2024年阿里云服务器租用费用&#xff0c;云服务器ECS经济型e实例2核2G、3M固定带宽99元一年&#xff0c;轻量应用服务器2核2G3M带宽轻量服务器一年61元&#xff0c;ECS u1服务器2核4G5M固定带宽199元一年&#xff0c;2核4G4M带宽轻量服务器一年165元12个月&#xff0c;2核4G服务…

IntelliJ IDEA中文---强化智能编码与重构,提升开发效率

IntelliJ IDEA 2023是一款功能强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;专为Java开发人员设计。它支持智能代码编辑、自动补全和重构&#xff0c;帮助开发者提高编码效率。同时&#xff0c;内置了丰富的调试工具&#xff0c;支持断点调试和变量监视&#xff…

STM32-04基于HAL库(CubeMX+MDK+Proteus)中断案例(按键中断扫描)

文章目录 一、功能需求分析二、Proteus绘制电路原理图三、STMCubeMX 配置引脚及模式&#xff0c;生成代码四、MDK打开生成项目&#xff0c;编写HAL库的按键检测代码五、运行仿真程序&#xff0c;调试代码 一、功能需求分析 在完成GPIO输入输出案例之后&#xff0c;开始新的功能…

2024阿里云老用户服务器优惠价格99元和199元

阿里云服务器租用价格表2024年最新&#xff0c;云服务器ECS经济型e实例2核2G、3M固定带宽99元一年&#xff0c;轻量应用服务器2核2G3M带宽轻量服务器一年61元&#xff0c;ECS u1服务器2核4G5M固定带宽199元一年&#xff0c;2核4G4M带宽轻量服务器一年165元12个月&#xff0c;2核…

[RK356X_LINUX] 关于UMS功能电脑不显示盘符

问题描述 根据356x_linux\docs\Linux\ApplicationNote\Rockchip_Quick_Start_Linux_USB_Gadget_CN.pdf文档执行命令配置UMS功能。 虽然电脑端显示有UMS设备图标&#xff0c;但无盘符显示。 在执行/etc/init.d/S50usbdevice restart后会出现打印&#xff1a; Starting /usr/b…

MySQL数据库 数据库基本操作(二):表的增删查改(上)

1. CRUD CRUD 即增加(Create)、查询(Retrieve)、更新(Update)、删除(Delete)四个单词的首字母缩写,就是数据库基本操作中针对表的一系列操作. 2. 新增(create) -->insert 语法: insert into 表名 [列名1,列名2…] values (val1,val2…) [注意] 列名可以没有,如果没有列名…

Delphi 是一种内存安全的语言吗?

上个月&#xff0c;美国政府发布了 "回到基石 "报告&#xff1a; 通往安全和可衡量软件之路 "的报告。该报告是美国网络安全战略的一部分&#xff0c;重点关注多个领域&#xff0c;包括内存安全漏洞和质量指标。 许多在线杂志都对这份报告进行了评论&#xff0…