关于SpringBean的个人学习总结

简介: Spring Bean 是由 Spring 容器管理的对象实例,通过配置元数据创建和装配,实现对象的集中管理和解耦。Bean 可通过构造方法、工厂等方式实例化,具备完整生命周期,支持初始化与销毁回调,提升应用的可维护性与灵活性。

Spring Bean 是什么

Bean 定义本质上是创建一个或多个对象的配方。容器在请求时查看有名称的Bean的配方,并使用该Bean定义所封装的配置元数据来创建(或获取)一个实际对象。

在 Spring 框架中,Bean 是指被 Spring 容器管理或者实例化的对象。Bean 可以是任何一个由 Java 实例,例如数据库连接、业务逻辑类、控制器等等。Spring Bean 实例的创建和管理是由 Spring 容器负责的,而不是应用程序本身。

Bean 给我们带来的优势主要是将对象的创建和管理和业务逻辑分离开,主打一个低耦合,让程序本身更易于维护和管理,比如在我们的项目中,连接数据库的创建和管理只需要交给 Spring 容器就行,业务逻辑在 Service层完成,当需要连接另一个数据库,只需要修改 Spring 的配置文件即可。

Bean 的作用范围

为什么Bean默认为单例?

  • 为了提高性能

适合交给容器进行管理的bean

  • 表现层对象
  • 业务层对象
  • 数据层对象
  • 工具对象

不适合交给容器进行管理的bean

  • 封装实体的域对象

实例化 Bean 的方式

构造方法

提供可使用的构造方法

public class BookServiceImpl implements BookService {
   
    public BookServiceImpl() {
   
        System.out.println(" book constructor...");
    }

    @Override
    public void schedule() {
   
        System.out.println("预定了一本书...");
    }
}

如果代码中只有无参构造的话,比如上面代码,那么里面的无参构造可以省略,Spring 会使用默认的无参构造,但是如果有带参构造的话,那就要显式写出无参构造

xml配置

<bean id="bookService" class="com.springbean.service.impl.BookServiceImpl"/>

如果不提供无参构造方法的话,就会抛出异常:

Caused by: java.lang.NoSuchMethodException: com.springbean.service.impl.BookServiceImpl.<init>()

实例工厂

使用FactoryBean实例化 bean

xml 配置

需要先配置一个工厂 bean

<bean id="bookFactory" class="com.springbean.appFroInstance.BookFacBean"/>

FactoryBean 实例

public class BookFac implements FactoryBean<BookService> {
   

    @Override
    public BookService getObject() throws Exception {
   
        return new BookServiceImpl();
    }

    @Override
    public Class<?> getObjectType() {
   
        return BookService.class;
    }

    @Override
    public boolean isSingleton() {
   
        return FactoryBean.super.isSingleton();
    }
}

静态工厂

xml 配置

<bean id="bookFactory" class="com.springbean.factory.StaticBookFactory" factory-method="getBookSchedule"/>

静态方法

public class StaticBookFactory {
   
    public static BookService getBookSchedule(){
   
        return new BookServiceImpl();
    }
}

Bean 的生命周期

演示链接

概念

bean 的生命周期

简单来说就是,bean从创建到销毁的整体过程

bean 的生命周期控制

bean创建后到销毁前做一些事情

生命周期过程

简要版

初始化容器

  1. 创建对象(内存分配)
  2. 执行构造方法
  3. 执行属性注入(set)
  4. 执行bean初始化方法

使用bean

  1. 执行业务操作

关闭 / 销毁容器

  1. 执行bean销毁方法

img

详细版

  • 实例化:Spring 容器根据配置文件或注解实例化对象
  • 属性注入:Spring 将依赖(通过 setter 或者字段注入)注入到 Bean 实例中
  • 初始化前的扩展机制:如果 Bean 实现了BeanNameAware等 aware 接口,则执行 aware 注入
  • 初始化前(BeanPostProcessor):在 Bean 初始化前,可以通过 BeanPostProcessor 接口对 Bean 进行一些额外的处理
  • 初始化:调用InitializingBean接口的afterPropertiesSet()方法或通过init-method属性指定的方法
  • 初始化后(BeanPostProcessor):在 Bean 初始化后,可以通过BeanPostProcessor进行进一步处理
  • 使用Bean:Bean 已经初始化完成,可以被容器中的其他 Bean 使用
  • 销毁:当容器关闭时,Spring 调用 DisposableBean 接口的destroy()或者通过destroy-method属性指定的销毁方法。

img

代码模拟

没添加set方法(属性注入)

1)xml 配置

<bean id="bookDao" class="com.springbean.dao.impl.BookDaoImpl" init-method="init" destroy-method="destroy"/>

2)业务逻辑代码

编写接口代码:

public interface BookDao {
   
    void save();

    void init();

    void destroy();
}

实现类:

public class BookDaoImpl implements BookDao {
   
    @Override
    public void save() {
   
        System.out.println("book dao save...");
    }

    @Override
    public void init() {
   
        System.out.println("init...");
    }

    @Override
    public void destroy() {
   
        System.out.println("destroy...");
    }
}

3)测试代码:

public class BookMain {
   
    public static void main(String[] args) {
   
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

        applicationContext.registerShutdownHook();
        BookDao bookDao = (BookDao) applicationContext.getBean("bookDao");

        bookDao.save();

//        applicationContext.close();
    }
}

registerShutdownHookSpring框架中ConfigurableApplicationContext接口的一个方法,用于注册一个JVM关闭钩子

作用:在JVM关闭的时候,确保Spring容器可以优雅关闭,并执行所有单例bean的销毁回调方法

工作原理

  1. 注册钩子:向 JVM 注册一个关闭钩子线程
  2. JVM 关闭时触发:当 JVM 收到关闭信号(如 Ctrl+C、系统关闭等)时,会调用这个钩子
  3. 关闭 Spring 容器:钩子线程会调用 ApplicationContextclose() 方法
  4. 执行销毁回调:Spring 会调用所有单例 bean 的销毁方法(如 @PreDestroyDisposableBean 接口、destroy-method 等)

在虚拟机退出前先关闭容器再退出虚拟机

4)执行结果:

init...
book dao save...
destroy...

添加set

在业务逻辑中添加set方法的bean初始化容器的顺序变化

1)先看执行结果的变化

# 创建对象
init...  
# 执行构造方法
service constructor...
# 执行属性注入
service set ...
# 执行 bean 初始化方法
service init...
# 执行业务操作
预定了一本书...
book dao save...
# 关闭销毁容器
service destroy...
destroy...

2)添加set之后的xml配置

<bean id="bookService" class="com.springbean.service.impl.BookServiceImpl">
  <property name="bookDao" ref="bookDao"/>
</bean>

3)业务逻辑代码

实现InitializingBean, DisposableBean接口

public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
   

    private BookDao bookDao;

    public BookServiceImpl() {
   
        System.out.println("service constructor...");
    }

    @Override
    public void schedule() {
   
        System.out.println("预定了一本书...");
        bookDao.save();
    }

    public void setBookDao(BookDao bookDao) {
   
        System.out.println("service set ...");
        this.bookDao = bookDao;
    }

    public void destroy() throws Exception{
   
        System.out.println("service destroy...");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
   
        System.out.println("service init...");
    }
}

afterPropertiesSet:初始化回调

源码解释:

由包含的BeanFactory在设置所有bean属性并满足BeanFactoryAwareApplicationContextAware等条件后调用。该方法允许bean实例在已设置所有bean属性时对其整体配置和最终初始化进行验证。

抛出异常: 在出现配置错误(例如未能设置一个必要属性)或由于其他任何原因初始化失败的情况下

4)测试函数代码:

public class BookMain {
   
    public static void main(String[] args) {
   
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

        applicationContext.registerShutdownHook();

        BookDao bookDao = (BookDao) applicationContext.getBean("bookDao");
        BookService bookService = (BookService) applicationContext.getBean("bookService");
        bookService.schedule();

    }
}
相关文章
|
10月前
|
设计模式 安全 Java
Java设计模式(一):单例模式与工厂模式
本文详解单例模式与工厂模式的核心实现及应用,涵盖饿汉式、懒汉式、双重检查锁、工厂方法、抽象工厂等设计模式,并结合数据库连接池与支付系统实战案例,助你掌握设计模式精髓,提升代码专业性与可维护性。
|
7月前
|
搜索推荐 JavaScript 关系型数据库
基于用户评论分析挖掘的旅游景点推荐系统
本研究基于用户评论分析,构建个性化旅游景点推荐系统。融合自然语言处理与情感分析技术,挖掘游客真实偏好,结合Django、Vue.js与MySQL等技术实现系统开发,提升旅游决策效率与体验质量,推动旅游产业智能化发展。
|
7月前
|
消息中间件 监控 Kafka
从“数据堆积如山”到“实时驱动业务”——聊聊Kafka到Flink的实时数据处理演进
从“数据堆积如山”到“实时驱动业务”——聊聊Kafka到Flink的实时数据处理演进
446 3
|
7月前
|
关系型数据库 Java MySQL
《理解MySQL数据库》InnoDB事务深度解析
本文深入解析InnoDB事务机制,涵盖ACID特性、隔离级别、MVCC、锁机制及Spring事务管理,结合SQL与Java代码示例,系统阐述事务原理与最佳实践,助力构建高性能、高可靠数据库应用。
|
8月前
|
数据库 数据中心 数据库管理
【赵渝强老师】OceanBase的内存管理
OceanBase数据库采用多租户架构,内存分为500虚拟租户、系统租户和业务租户三类。通过memory_limit_percentage和memory_limit参数控制OBServer节点总内存上限,并在创建Resource Unit时设定业务租户内存,实现资源隔离与管理。
444 0
|
缓存 安全 Java
Spring Boot 3 集成 Spring Security + JWT
本文详细介绍了如何使用Spring Boot 3和Spring Security集成JWT,实现前后端分离的安全认证概述了从入门到引入数据库,再到使用JWT的完整流程。列举了项目中用到的关键依赖,如MyBatis-Plus、Hutool等。简要提及了系统配置表、部门表、字典表等表结构。使用Hutool-jwt工具类进行JWT校验。配置忽略路径、禁用CSRF、添加JWT校验过滤器等。实现登录接口,返回token等信息。
7744 14
Spring Boot 3 集成 Spring Security + JWT
|
SQL JavaScript Java
Spring Boot 3 整合 Mybatis-Plus 实现数据权限控制
本文介绍了如何在Spring Boot 3中整合MyBatis-Plus实现数据权限控制,通过使用MyBatis-Plus提供的`DataPermissionInterceptor`插件,在不破坏原有代码结构的基础上实现了细粒度的数据访问控制。文中详细描述了自定义注解`DataScope`的使用方法、`DataPermissionHandler`的具体实现逻辑,以及根据用户的不同角色和部门动态添加SQL片段来限制查询结果。此外,还展示了基于Spring Boot 3和Vue 3构建的前后端分离快速开发框架的实际应用案例,包括项目的核心功能模块如用户管理、角色管理等,并提供Gitee上的开源仓库
3504 11
|
Java API 存储
Java如何对List进行排序?
【7月更文挑战第26天】
2358 9
Java如何对List进行排序?
|
SQL 存储 数据库
OceanBase数据库优化
【8月更文挑战第14天】OceanBase数据库优化
787 2
|
Linux 应用服务中间件 nginx
Linux 快速搭建 Overleaf 5.0 附中文字体及完整 TexLive 安装教程(2024最新版)
2024最新版 Linux 极速安装 Overleaf 5.0 手把手教学!附 XeLatex 修复,新增中文字体以及安装完整版 TexLive 教程!