Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界 (下)

简介: Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界

Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界 (上):https://developer.aliyun.com/article/1456573


Bean 的作用域和生命周期管理


解析 Bean 的作用域和生命周期概念


在Spring框架中,理解Bean的作用域和生命周期是至关重要的,它们决定了Bean的创建、管理及销毁方式。本篇博客将深入探讨这两个概念,并通过示例代码帮助读者更好地理解Spring提供的各种Bean生命周期回调方法。


一、Bean的作用域(Scope)


在Spring中,Bean的作用域决定了容器如何新建Bean实例的规则。Spring提供了几种作用域:


  • singleton:(默认作用域)容器中只存在一个共享的Bean实例,每次请求都返回同一个Bean实例。
  • prototype:每次请求都会创建一个新的Bean实例。
  • request:每次HTTP请求都会产生一个新的Bean,仅在Web应用中有效。
  • session:在一个HTTP Session中,一个Bean定义对应一个实例。仅在Web应用中有效。
  • application:在一个ServletContext生命周期内,一个Bean定义对应一个实例。仅在Web应用中有效。


示例代码:定义不同作用域的Bean

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
 
@Configuration
public class BeanScopeConfig {
 
    @Bean
    @Scope("singleton")
    public MyBean singletonBean() {
        return new MyBean();
    }
 
    @Bean
    @Scope("prototype")
    public MyBean prototypeBean() {
        return new MyBean();
    }
}


二、Bean的生命周期


Bean的生命周期指的是从Bean的初始化到销毁的整个过程。在这个过程中,Spring容器提供了多个扩展点,允许在Bean的创建和销毁过程中加入自定义逻辑。


Bean生命周期的主要阶段:


  1. 实例化Bean:Spring容器首先调用构造函数或工厂方法来实例化Bean。
  2. 填充属性:Spring容器注入Bean所需要的依赖。
  3. 调用BeanNameAware的setBeanName():如果Bean实现了BeanNameAware接口,Spring容器将Bean的ID传给setBeanName方法。
  4. 调用BeanFactoryAware的setBeanFactory():如果Bean实现了BeanFactoryAware接口,Spring容器将调用setBeanFactory方法,传入BeanFactory。
  5. 调用ApplicationContextAware的setApplicationContext():如果Bean实现了ApplicationContextAware接口,Spring容器将调用setApplicationContext方法,传入ApplicationContext。
  6. 前置处理器Before Initialization:BeanPostProcessor的postProcessBeforeInitialization方法将被调用。
  7. 初始化:如果Bean实现了InitializingBean接口,Spring容器将调用afterPropertiesSet方法。另外,可以通过@Bean注解的initMethod指定初始化方法。
  8. 后置处理器After Initialization:BeanPostProcessor的postProcessAfterInitialization方法将被调用。
  9. Bean准备就绪:此时,Bean已经准备好被应用使用了。
  10. 销毁:当容器关闭时,如果Bean实现了DisposableBean接口,Spring容器将调用destroy方法。也可以通过@Bean注解的destroyMethod指定销毁方法。


示例代码:自定义Bean生命周期回调方法

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
 
public class MyLifecycleBean implements InitializingBean, DisposableBean {
 
    @Override
    public void afterPropertiesSet() throws Exception {
        // 初始化逻辑
        System.out.println("MyLifecycleBean is initialized.");
    }
 
    @Override
    public void destroy() throws Exception {
        // 销毁逻辑
        System.out.println("MyLifecycleBean is destroyed.");
    }
}

通过实现InitializingBeanDisposableBean接口,我们可以在Bean的生命周期的特定时间点执行自定义逻辑。


Bean 的属性装配和自动装配


深入理解Spring Bean:属性、依赖与自动装配


在Spring框架中,Bean是构建应用程序的基石。它们不仅承载着数据和行为,还通过依赖关系与其他Bean相互作用。正确地管理Bean的属性和依赖关系,是实现高效、可维护Spring应用的关键。本篇博客将带你深入理解Bean的属性和依赖关系,并掌握Spring提供的属性配置和自动装配方式。


一、理解Bean的属性和依赖关系


Bean的属性


Bean的属性指的是Bean中的字段,这些字段可以通过XML配置、注解或JavaConfig来配置。


示例:通过XML配置Bean属性
<bean id="exampleBean" class="com.example.ExampleBean">
    <property name="beanProperty" value="Some Value"/>
</bean>


示例:通过注解配置Bean属性
@Component
public class ExampleBean {
    @Value("${some.value}")
    private String beanProperty;
}


Bean的依赖关系


Bean的依赖关系指的是一个Bean依赖于另一个Bean来完成其操作。例如,一个服务类(Service)可能依赖于一个数据访问对象(DAO)。


示例:通过XML配置Bean依赖
<bean id="myDao" class="com.example.MyDao"/>
 
<bean id="myService" class="com.example.MyService">
    <property name="myDao" ref="myDao"/>
</bean>


示例:通过注解配置Bean依赖
@Service
public class MyService {
    private final MyDao myDao;
 
    @Autowired
    public MyService(MyDao myDao) {
        this.myDao = myDao;
    }
}


二、掌握Spring提供的属性配置和自动装配方式


属性配置


Spring提供了多种方式来配置Bean的属性,其中最常用的是@Value注解。


使用@Value注解


@Value注解可以用来注入普通属性、系统属性、环境变量等。

@Component
public class ExampleBean {
    @Value("${app.name:defaultAppName}")
    private String appName;
}

自动装配


Spring的自动装配功能可以自动满足Bean之间的依赖,减少配置的工作量。最常用的自动装配注解是@Autowired


使用@Autowired进行自动装配


Spring会在容器中查找匹配类型的Bean,并注入到被@Autowired标注的字段、构造器或方法中。

@Service
public class MyService {
    private final MyDao myDao;
 
    @Autowired
    public MyService(MyDao myDao) {
        this.myDao = myDao; // 自动装配
    }
}


高级自动装配


对于更复杂的自动装配场景,Spring提供了@Qualifier@Primary注解来进一步控制自动装配的行为。


使用@Qualifier指定具体的Bean


当有多个同类型的Bean可供选择时,@Qualifier注解可以用来指定具体要装配的Bean。

@Autowired
@Qualifier("specificDao")
private MyDao myDao;


使用@Primary指定首选的Bean


通过在Bean定义上使用@Primary注解,可以指定当存在多个同类型Bean时,默认选择哪一个。

@Component
@Primary
public class PrimaryDao implements MyDao {
    // 实现细节
}


高级特性:BeanPostProcessor 和 FactoryBean


理解 BeanPostProcessor 和 FactoryBean 的作用和区别


在Spring框架中,BeanPostProcessor和FactoryBean是两个非常重要的接口,它们在Bean的生命周期管理和创建过程中扮演着关键角色。虽然它们的功能看似相近,但实际上各自的作用和应用场景大相径庭。


BeanPostProcessor:定制Bean的创建过程


BeanPostProcessor允许开发者插手Bean的初始化过程,在Bean的初始化前后执行一些自定义逻辑。


主要方法:


  • postProcessBeforeInitialization(Object bean, String beanName): 在任何Bean初始化回调方法(如InitializingBean的afterPropertiesSet或自定义的init方法)之前调用。
  • postProcessAfterInitialization(Object bean, String beanName): 在所有Bean初始化回调之后调用。


应用场景:


  • 修改或包装Bean的实例,例如用代理包装一个Bean以提供额外的功能。
  • 检查Bean属性的正确性或根据特定条件更改Bean的属性。


示例代码:

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
 
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 在初始化之前执行的逻辑
        return bean;
    }
 
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // 在初始化之后执行的逻辑
        return bean;
    }
}


FactoryBean:专门用于生产对象的工厂Bean


与BeanPostProcessor不同,FactoryBean是用于生成其他Bean实例的特殊Bean。当配置的Bean实现了FactoryBean接口时,它将返回getObject()方法所返回的对象,而不是FactoryBean本身。


主要方法:


  • T getObject(): 返回由FactoryBean创建的Bean实例。
  • Class<?> getObjectType(): 返回FactoryBean创建的Bean类型。
  • boolean isSingleton(): 表明由FactoryBean创建的Bean是否为单例。


应用场景:


  • 创建复杂对象,当一个Bean的创建过程中涉及复杂逻辑时,可以使用FactoryBean封装这些逻辑。
  • 返回的Bean实例可以是接口的代理,也可以是需要复杂初始化的对象。


示例代码:

import org.springframework.beans.factory.FactoryBean;
 
public class MyFactoryBean implements FactoryBean<MyBean> {
    @Override
    public MyBean getObject() throws Exception {
        // 返回需要创建的Bean实例
        return new MyBean();
    }
 
    @Override
    public Class<?> getObjectType() {
        return MyBean.class;
    }
 
    @Override
    public boolean isSingleton() {
        // 控制该Bean是否为单例
        return true;
    }
}


BeanPostProcessor vs FactoryBean


虽然BeanPostProcessor和FactoryBean都可以影响Spring容器中Bean的创建,但它们的主要区别在于:


  • BeanPostProcessor是用于修改或包装已经存在的Bean实例的。
  • FactoryBean是用于创建新的Bean实例的。


Spring Boot 中的 Bean 管理和自动配置


探索Spring Boot:设计理念与自动配置深解


Spring Boot,作为现代Java开发中的一颗明星,以其“约定大于配置”的理念,极大地简化了Spring应用的开发、部署和运维。它不仅继承了Spring框架强大的依赖注入和面向切面编程的特性,还在此基础上提供了自动配置等功能,使得开发者可以更加专注于业务逻辑。本篇博客将带你深入理解Spring Boot的设计理念和主要特点,以及它在Bean管理和自动配置方面的实现原理。


Spring Boot的设计理念和主要特点


设计理念


Spring Boot遵循“约定大于配置”的原则,旨在减少项目搭建的复杂性和开发时的配置要求。它通过合理的默认配置,帮助开发者快速启动和开发Spring应用程序。


主要特点


  • 自动配置:自动配置Spring和第三方库,尽可能地减少配置文件的使用。
  • 独立运行:生成的应用程序可以直接运行,不需要外部的Servlet容器。
  • 运维友好:提供了丰富的监控和管理功能,支持健康检查、应用信息查看等。
  • 无代码生成和XML配置:不需要生成代码或进行XML配置,通过注解和自动装配完成配置。


深入掌握Spring Boot在Bean管理和自动配置方面的实现原理


Bean管理


Spring Boot利用Spring框架的依赖注入(DI)特性来管理Bean。开发者可以通过注解如@Component、@Service、@Repository等来声明Bean,并通过@Autowired或构造器注入依赖。


示例:定义和注入Bean
@Service
public class MyService {
    // 业务逻辑
}
 
@RestController
public class MyController {
    private final MyService myService;
 
    @Autowired
    public MyController(MyService myService) {
        this.myService = myService; // 自动装配
    }
}


自动配置原理


Spring Boot自动配置的魔法背后是@EnableAutoConfiguration注解,这个注解通过@Import引入了AutoConfigurationImportSelector类,该类负责读取META-INF/spring.factories文件中的配置,根据条件选择性地应用配置。


示例:自动配置的简化示例


假设我们有一个自动配置类MyAutoConfiguration,当classpath中存在某个特定类时,这个配置类就会被应用:

@Configuration
@ConditionalOnClass(SomeClass.class)
public class MyAutoConfiguration {
    @Bean
    public SomeBean someBean() {
        return new SomeBean();
    }
}


resources/META-INF/spring.factories文件中,我们声明这个自动配置类:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyAutoConfiguration


当Spring Boot应用启动时,如果classpath中存在SomeClass,那么SomeBean就会被自动配置。

目录
打赏
0
0
0
0
34
分享
相关文章
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
163 26
什么是Spring IOC 和DI ?
IOC : 控制翻转 , 它把传统上由程序代码直接操控的对象的调用权交给容 器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转 移,从程序代码本身转移到了外部容器。 DI : 依赖注入,在我们创建对象的过程中,把对象依赖的属性注入到我们的类中。
【SpringFramework】Spring IoC-基于XML的实现
本文主要讲解SpringFramework中IoC和DI相关概念,及基于XML的实现方式。
126 69
【SpringFramework】Spring IoC-基于注解的实现
本文主要记录基于Spring注解实现IoC容器和DI相关知识。
72 21
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
101 12
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于 xml 的整合
本教程介绍了基于XML的MyBatis整合方式。首先在`application.yml`中配置XML路径,如`classpath:mapper/*.xml`,然后创建`UserMapper.xml`文件定义SQL映射,包括`resultMap`和查询语句。通过设置`namespace`关联Mapper接口,实现如`getUserByName`的方法。Controller层调用Service完成测试,访问`/getUserByName/{name}`即可返回用户信息。为简化Mapper扫描,推荐在Spring Boot启动类用`@MapperScan`注解指定包路径避免逐个添加`@Mapper`
24 0
微服务——SpringBoot使用归纳——Spring Boot集成Thymeleaf模板引擎——Thymeleaf 介绍
本课介绍Spring Boot集成Thymeleaf模板引擎。Thymeleaf是一款现代服务器端Java模板引擎,支持Web和独立环境,可实现自然模板开发,便于团队协作。与传统JSP不同,Thymeleaf模板可以直接在浏览器中打开,方便前端人员查看静态原型。通过在HTML标签中添加扩展属性(如`th:text`),Thymeleaf能够在服务运行时动态替换内容,展示数据库中的数据,同时兼容静态页面展示,为开发带来灵活性和便利性。
23 0
微服务——SpringBoot使用归纳——Spring Boot中的项目属性配置——少量配置信息的情形
本课主要讲解Spring Boot项目中的属性配置方法。在实际开发中,测试与生产环境的配置往往不同,因此不应将配置信息硬编码在代码中,而应使用配置文件管理,如`application.yml`。例如,在微服务架构下,可通过配置文件设置调用其他服务的地址(如订单服务端口8002),并利用`@Value`注解在代码中读取这些配置值。这种方式使项目更灵活,便于后续修改和维护。
14 0
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录—— application.yml 中对日志的配置
在 Spring Boot 项目中,`application.yml` 文件用于配置日志。通过 `logging.config` 指定日志配置文件(如 `logback.xml`),实现日志详细设置。`logging.level` 可定义包的日志输出级别,例如将 `com.itcodai.course03.dao` 包设为 `trace` 级别,便于开发时查看 SQL 操作。日志级别从高到低为 ERROR、WARN、INFO、DEBUG,生产环境建议调整为较高级别以减少日志量。本课程采用 yml 格式,因其层次清晰,但需注意格式要求。
22 0
|
10天前
|
基于SpringBoot的Redis开发实战教程
Redis在Spring Boot中的应用非常广泛,其高性能和灵活性使其成为构建高效分布式系统的理想选择。通过深入理解本文的内容,您可以更好地利用Redis的特性,为应用程序提供高效的缓存和消息处理能力。
115 79

热门文章

最新文章