欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > java >内容正文

java

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

发布时间:2025/3/21 java 31 豆豆
生活随笔 收集整理的这篇文章主要介绍了 Spring5源码 - 02 Bean和Java对象的区别与猜想验证BeanDefinition 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

文章目录

  • 问题
  • 加载流程
  • BeanFactoryPostProcessor的执行时机
  • Code


问题

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


加载流程


BeanFactoryPostProcessor的执行时机

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

  • 在bean被转换成BeanDefinition之后
  • 在实例化bean之前
  • 中间这个部分,如果用户实现了BeanFactoryPostProcessor接口,则可以对BeanDefinition进行修改


    Code

    演示下这个功能

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

    package com.artisan.bd;import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;@Component public class Artisan1 {@PostConstructpublic 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));} }

    同时我们也看到了 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*/@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {// 取出A对应的 beanDefinition -----> 这时候bd中存放的类是A.classGenericBeanDefinition beanDefinition = (GenericBeanDefinition) beanFactory.getBeanDefinition("artisan1");//ScannedGenericBeanDefinition beanDefinition1 = (ScannedGenericBeanDefinition) beanFactory.getBeanDefinition("artisan1");// 将bd中的beanclass修改为BbeanDefinition.setBeanClass(Artisan2.class);} }


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

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

    再此执行刚才的代码

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


    再比如说修改scope

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

    总结

    以上是生活随笔为你收集整理的Spring5源码 - 02 Bean和Java对象的区别与猜想验证BeanDefinition的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。