关于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();

    }
}
相关文章
|
12月前
|
设计模式 安全 Java
Java设计模式(一):单例模式与工厂模式
本文详解单例模式与工厂模式的核心实现及应用,涵盖饿汉式、懒汉式、双重检查锁、工厂方法、抽象工厂等设计模式,并结合数据库连接池与支付系统实战案例,助你掌握设计模式精髓,提升代码专业性与可维护性。
|
9月前
|
缓存 Java Spring
JDK-CGLIB-反射
JDK动态代理基于接口,利用反射和Proxy实现;CGLIB通过ASM生成子类,支持无接口类代理,但无法代理final方法。二者性能随JDK版本变化,JDK8后差距缩小。Spring AOP根据是否有接口自动选择代理方式。Java反射机制则允许运行时获取类信息并动态操作对象,是动态代理的基础。
278 0
|
9月前
|
SQL 缓存 Java
关于synchronized-reentrantlock-volatile学习总结1.0
`synchronized`是Java内置的原子性锁,基于Monitor实现,保证线程间操作的原子性、可见性与有序性。`ReentrantLock`是JUC提供的显式锁,支持公平/非公平、可中断、超时获取等高级功能。`volatile`仅保证变量可见性与禁止重排,适用于轻量级场景。三者各有适用场景,需根据需求选择。
193 14
|
9月前
|
安全 Java 容器
Java的ConcurrentModificationException异常介绍和解决方案
ConcurrentModificationException(CME)是Java中一种快速失败(fail-fast)机制,当线程遍历集合时,若集合结构被修改(如add、remove),则抛出该异常。其原理基于`modCount`与`expectedModCount`的不一致。常见于ArrayList、HashMap等非线程安全集合。解决方法包括:使用Iterator.remove()、CopyOnWriteArrayList、倒序遍历、removeIf()或并发容器如ConcurrentHashMap,以避免并发修改问题。
559 0
|
缓存 安全 Java
Spring Boot 3 集成 Spring Security + JWT
本文详细介绍了如何使用Spring Boot 3和Spring Security集成JWT,实现前后端分离的安全认证概述了从入门到引入数据库,再到使用JWT的完整流程。列举了项目中用到的关键依赖,如MyBatis-Plus、Hutool等。简要提及了系统配置表、部门表、字典表等表结构。使用Hutool-jwt工具类进行JWT校验。配置忽略路径、禁用CSRF、添加JWT校验过滤器等。实现登录接口,返回token等信息。
7926 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上的开源仓库
3638 11
|
XML Java 数据格式
异步编程 - 08 Spring框架中的异步执行_TaskExecutor接口和@Async应用篇
异步编程 - 08 Spring框架中的异步执行_TaskExecutor接口和@Async应用篇
895 0
|
Java API 存储
Java如何对List进行排序?
【7月更文挑战第26天】
2405 9
Java如何对List进行排序?
|
SQL 存储 数据库
OceanBase数据库优化
【8月更文挑战第14天】OceanBase数据库优化
814 2
|
Linux 应用服务中间件 nginx
Linux 快速搭建 Overleaf 5.0 附中文字体及完整 TexLive 安装教程(2024最新版)
2024最新版 Linux 极速安装 Overleaf 5.0 手把手教学!附 XeLatex 修复,新增中文字体以及安装完整版 TexLive 教程!

热门文章

最新文章