Spring5源码 - 02 Bean和Java对象的区别与猜想验证BeanDefinition

简介: Spring5源码 - 02 Bean和Java对象的区别与猜想验证BeanDefinition

20200914143739548.png


问题

Spring创建的Bean 和 我们提供的Class对象 有什么关系吗? 一定是我们提供的这个对象实例吗?


加载流程



20200916090019877.png



BeanFactoryPostProcessor的执行时机


结合上图的流程,我们可以得出如下结论

  1. 在bean被转换成BeanDefinition之后
  2. 在实例化bean之前


中间这个部分,如果用户实现了BeanFactoryPostProcessor接口,则可以对BeanDefinition进行修改


Code

演示下这个功能


2020091601290443.png


两个类 一个可以被Spring扫描到的bean Artisan1 , 另外一个是普通的对象 Artisan2

package com.artisan.bd;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class Artisan1 {
  @PostConstruct
  public void  init(){
    System.out.println("Artisan1 Created");
  }
}


标注了 @Component

package com.artisan.bd;
import javax.annotation.PostConstruct;
public class Artisan2 {
}


普通对象


配置类

package com.artisan.bd;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.artisan.bd")
public class AppConfig {
}


测试类

package com.artisan.bd;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
  public static void main(String[] args) {
    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
    System.out.println(ac.getBean(Artisan1.class));
    System.out.println(ac.getBean(Artisan2.class));
  }
}


20200916013416918.png

同时我们也看到了 Artisan1这个对象,对应的 BeanDefinition中的beanClass也是 Artisan1 .


那能改么? 能改成Artisan2吗?


看了刚才的流程图,我们知道如果实现了BeanFactoryPostProcessor接口,就可以修改BeanDefinition。


试试吧

package com.artisan.bd;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.stereotype.Component;
@Component
public class ArtisanBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
  /**
   * beanFactory 就是流程图中的 bdmap    BeanDefinition的map集合
   * @param beanFactory the bean factory used by the application context
   * @throws BeansException
   */
  @Override
  public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    // 取出A对应的 beanDefinition -----> 这时候bd中存放的类是A.class
    GenericBeanDefinition beanDefinition = (GenericBeanDefinition) beanFactory.getBeanDefinition("artisan1");
    //ScannedGenericBeanDefinition beanDefinition1 = (ScannedGenericBeanDefinition) beanFactory.getBeanDefinition("artisan1");
    // 将bd中的beanclass修改为B
    beanDefinition.setBeanClass(Artisan2.class);
  }
}


20200916085458412.png

使用实现类来接收 beanFactory.getBeanDefinition(“artisan1”) 的返回值,可用方法更多,接口中的方法太少,并且也木有我们要用的setBeanClassName 方法。


别忘了加@Component,不然spring无法扫描到,这个就不会生效 。


再此执行刚才的代码

20200916014024300.png


20200916014253611.png


同时,通过name artisan1 获取到的bean 其实是被修改后了的, 因为Sping根据用户提供的Artisan2, 实例化了Artisan2


20200916090230642.png


再比如说修改scope

20200916014816748.png20200916014855683.png


都明白了哈, 后面从源码的角度分析 ~


相关文章
|
14天前
|
XML 安全 Java
|
15天前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
35 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
17天前
|
Java 程序员
Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
小米,29岁程序员,分享了一次面试经历,详细解析了Java中&和&&的区别及应用场景,展示了扎实的基础知识和良好的应变能力,最终成功获得Offer。
45 14
|
1月前
|
缓存 Java Spring
实战指南:四种调整 Spring Bean 初始化顺序的方案
本文探讨了如何调整 Spring Boot 中 Bean 的初始化顺序,以满足业务需求。文章通过四种方案进行了详细分析: 1. **方案一 (@Order)**:通过 `@Order` 注解设置 Bean 的初始化顺序,但发现 `@PostConstruct` 会影响顺序。 2. **方案二 (SmartInitializingSingleton)**:在所有单例 Bean 初始化后执行额外的初始化工作,但无法精确控制特定 Bean 的顺序。 3. **方案三 (@DependsOn)**:通过 `@DependsOn` 注解指定 Bean 之间的依赖关系,成功实现顺序控制,但耦合性较高。
实战指南:四种调整 Spring Bean 初始化顺序的方案
|
12天前
|
Java
java中面向过程和面向对象区别?
java中面向过程和面向对象区别?
17 1
|
12天前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
25 1
|
22天前
|
存储 缓存 安全
java 中操作字符串都有哪些类,它们之间有什么区别
Java中操作字符串的类主要有String、StringBuilder和StringBuffer。String是不可变的,每次操作都会生成新对象;StringBuilder和StringBuffer都是可变的,但StringBuilder是非线程安全的,而StringBuffer是线程安全的,因此性能略低。
42 8
|
26天前
|
Java 数据库连接 API
Spring 框架的介绍(Java EE 学习笔记02)
Spring是一个由Rod Johnson开发的轻量级Java SE/EE一站式开源框架,旨在解决Java EE应用中的多种问题。它采用非侵入式设计,通过IoC和AOP技术简化了Java应用的开发流程,降低了组件间的耦合度,支持事务管理和多种框架的无缝集成,极大提升了开发效率和代码质量。Spring 5引入了响应式编程等新特性,进一步增强了框架的功能性和灵活性。
42 0
|
2月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
210 2