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

举报
小工匠 发表于 2021/09/10 01:09:34 2021/09/10
【摘要】 文章目录 问题加载流程BeanFactoryPostProcessor的执行时机Code 问题 Spring创建的Bean 和 我们提供的Class对象 有什么关系吗? 一定是我们...

在这里插入图片描述


问题

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


加载流程

在这里插入图片描述


BeanFactoryPostProcessor的执行时机

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

  1. 在bean被转换成BeanDefinition之后
  2. 在实例化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 {
	
	@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));

	}
}


  

在这里插入图片描述

同时我们也看到了 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);

	}
}


  

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

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

再此执行刚才的代码

在这里插入图片描述

在这里插入图片描述

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

在这里插入图片描述


再比如说修改scope

在这里插入图片描述

在这里插入图片描述

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

文章来源: artisan.blog.csdn.net,作者:小小工匠,版权归原作者所有,如需转载,请联系作者。

原文链接:artisan.blog.csdn.net/article/details/108587569

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。