Spring底层架构核心概念

本文深入探讨了Spring框架的核心概念,包括BeanDefinition的详细解释,如Bean的作用域、初始化方法和销毁方法等。文章还介绍了不同类型的Bean定义方式,如XML、注解以及编程式定义,并通过AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner来解析和注册Bean。此外,讲解了BeanFactory和ApplicationContext的层级关系,以及它们在创建、管理Bean过程中的作用。同时,文章涵盖了类型转化、事件发布、国际化和资源加载等Spring的重要特性。
摘要由CSDN通过智能技术生成

BeanDefinition

其实底层是个接口

BeanDefinition表示Bean定义,BeanDefinition中存在很多属性用来描述一个Bean的特点。比如:

  • class,表示Bean类型(其实叫beanClass)
  • scope,表示Bean作用域,单例或原型等
  • lazyInit:表示Bean是否是懒加载
  • initMethodName:表示Bean初始化时要执行的方法
  • destroyMethodName:表示Bean销毁时要执行的方法
  • 还有很多...

在Spring中,我们经常会通过以下几种方式来定义Bean:

  1. <bean/>
  2. @Bean
  3. @Component(@Service,@Controller)

这些,我们可以称之声明式定义Bean

如果底层用的xml,spring也会解析成一个beanDefinition对象

bean注解解析也会生成beanDefinition

这里加了Bean注解直接调用这个方法对吗?

不太对,

首先会生成BeanDefinition对象,然后放到BeanDefinitionMap里面,再从map里面取出非懒加载的单例bean再拿出来,才会调用这个方法。

(Spring提供定义bean的方式)

我们还可以编程式定义Bean,那就是直接通过BeanDefinition,比如:

也就是说这个编程式定义Bean可以替代@Bean注解的一种写法。

(但是平常不会这么干,spring底层是这么干的)

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

// 生成一个BeanDefinition对象,并设置beanClass为User.class,并注册到ApplicationContext中
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(User.class);
// 还能指定作用域
beanDefinition.setScope("prototype");
// 指定beanName
context.registerBeanDefinition("user", beanDefinition);

System.out.println(context.getBean("user"));

我们还可以通过BeanDefinition设置一个Bean的其他属性

beanDefinition.setScope("prototype"); // 设置作用域
beanDefinition.setInitMethodName("init"); // 设置初始化方法
beanDefinition.setLazyInit(true); // 设置懒加载

和申明式事务、编程式事务类似,通过<bean/>,@Bean,@Component等申明式方式所定义的Bean,最终都会被Spring解析为对应的BeanDefinition对象,并放入Spring容器中。

被注解的BeanDefinitionReader(BeanDefinition的一个读取器 spring提供的一个工具类)

AnnotatedBeanDefinitionReader

可以直接把某个类转换为BeanDefinition,并且会解析该类上的注解,比如

// 先构造一个spring的容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
// 读到哪里去 肯定读到容器 所以要传参一个context
AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(context);
// 利用了BeanDefinition的一个读取器去注册了一个User
// 将User.class解析为BeanDefinition  也就是最终这个User就会成为BeanDefinition,放在spring容器里
annotatedBeanDefinitionReader.register(User.class);

System.out.println(context.getBean("user"));

register底层源码:这里只传了一个类User.class

构造了一个BeanDefinition,类就是传进来的类

然后还会去判断当前类上有没有@Lazy注解之类的,然后设置到刚才的BeanDefinition中

注意:它能解析的注解是:@Conditional,@Scope、@Lazy、@Primary、@DependsOn、@Role、@Description

User也没加注解

运行正常,说明我们的User是一个bean,报错就说明不是bean

比如AnnotationConfigApplicationContext底层就调用到了这个

被注解的BeanDefinitionReader(BeanDefinition的一个读取器 spring提供的一个工具类)

这个register底层其实就是调用的这个BeanDefinition的一个读取器

小总结:

他就是BeanDefinition的一个读取器 ,传给他一个类,他就能解析类上面的注解,然后变成一个BeanDefinition,然后放到spring的容器中,然后就成为了一个bean。

XmlBeanDefinitionReader

可以解析xml文件的,解析<bean/>标签

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(context);
int i = xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");

System.out.println(context.getBean("user"));

这里就不会报错,能拿到bean,底层解析xml

ClassPathBeanDefinitionScanner

ClassPathBeanDefinitionScanner是扫描器,但是它的作用和BeanDefinitionReader类似,它可以进行扫描,扫描某个包路径,对扫描到的类进行解析,比如,扫描到的类上如果存在@Component注解,那么就会把这个类解析为一个BeanDefinition,比如:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.refresh();

ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
// 定义扫描路径 扫描得到的都是BeanDefinition 然后放到spring容器
scanner.scan("com.zhouyu");

System.out.println(context.getBean("userService"));
例子:

在UserService上加了@Component注解

问:能拿到UserService这个bean吗?

答:不行 因为这里构造了空的spring容器,没有传配置文件进去,而且没刷新

加个代码context.refresh();(强制要求,不过就算加了也没丝毫作用)

这里定义了扫描器,然后把容器传进扫描器里。然后去路径下扫描,发现有@Component注解,然后就生成BeanDefinition,接着会加入到spring容器里,这样就能拿到UserService的bean了

我们的spring容器 也就是这个context,既可以注册某一个类成为bean

也可以自己触发去扫描

用构造器的底层代码

底层先调用空的构造方法

再把传进来的类进行注册

通过AnnotatedBeanDefinitionReader进行注册 注册成为一个BeanDefinition

再去刷新

也可以这么操作实现一样的效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值