36.Spring整体源码架构前置核心概念解析

Spring中的概念和工作流程

BeanDefinition

BeanDefinition中存在很多属性用来描述一个Bean的特点

  • class,表示Bean类型
  • scope,表示Bean作用域,单例或原型等
  • lazyInit:表示Bean是否是懒加载
  • initMethodName:表示Bean初始化时要执行的方法
  • destroyMethodName:表示Bean销毁时要执行的方法

通过以下方式定义Bean

  • xml文档

  • @Bean

  • @Component @Service @Controller

  • 编程式定义Bean

            var context = new AnnotationConfigApplicationContext(AppConfig.class);
            var beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
    
            beanDefinition.setBeanClass(CourseService.class);
            context.registerBeanDefinition("courseService", beanDefinition);
            
            var courseService = (CourseService)context.getBean("courseService");
            courseService.test();
    

通过BeanDefinition设置一个Bean的其他属性

BeanDefinitionReader

我们使用Spring时用得少,但在Spring源码中用得多,相当于Spring源码的基础设施。

AnnotatedBeanDefinitionReader

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

XmlBeanDefinitionReader

解析<bean/>标签

ClassPathBeanDefinitionScanner

它的作用和BeanDefinitionReader类似,它可以进行扫描,扫描某个包路径,对扫描到的类进行解析

BeanFactory

BeanFactory会负责创建Bean,并且提供获取Bean的API

ApplicationContext

ApplicationContext是个接口,实际上也是一个BeanFactory,不过比BeanFactory更加强大

比较重要的实现类

  • AnnotationConfigApplicationContext
  • ClassPathXmlApplicationContext

资源加载

可以直接利用ApplicationContext获取某个文件的内容

获取运行时环境

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

Map<String, Object> systemEnvironment = context.getEnvironment().getSystemEnvironment();
System.out.println(systemEnvironment);

System.out.println("=======");

Map<String, Object> systemProperties = context.getEnvironment().getSystemProperties();
System.out.println(systemProperties);

System.out.println("=======");

MutablePropertySources propertySources = context.getEnvironment().getPropertySources();
System.out.println(propertySources);

System.out.println("=======");

System.out.println(context.getEnvironment().getProperty("NO_PROXY"));
System.out.println(context.getEnvironment().getProperty("sun.jnu.encoding"));
System.out.println(context.getEnvironment().getProperty("zhouyu"));

事件发布

//先定义一个事件监听器
@Bean
public ApplicationListener applicationListener() {
    return event -> System.out.println("接收到了一个事件");
}

类型转化

在Spring源码中,有可能需要把String转成其他类型,所以在Spring源码中提供了一些技术来更方便的做对象的类型转化,关于类型转化的应用场景, 后续看源码的过程中会遇到很多。

PropertyEditor

ConversionService

TypeConverter

OrderComparator

@Order注解或实现Ordered接口来执行值进行比较

BeanPostProcessor

可以定义一个或多个BeanPostProcessor,可以在任意一个Bean初始化之前以及初始化之后去额外的做一些用户自定义的逻辑

BeanFactoryPostProcessor

BeanPostProcessor是干涉Bean的创建过程,BeanFactoryPostProcessor是干涉BeanFactory的创建过程。

FactoryBean

通过FactoryBean,一个Bean的创建过程可以自定义

通过@Bean也可以自己生成一个对象作为Bean,那么和FactoryBean的区别是什么呢?其实在很多场景下他俩是可以替换的,但是站在原理层面来说的,区别很明显,@Bean定义的Bean是会经过完整的Bean生命周期的。

@ComponentScan的配置

ExcludeFilter

IncludeFilter

//没有@Component注解,它也会被扫描成为一个Bean。
@ComponentScan(value = "com.lywtimer",
        includeFilters  = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = TagService.class)})
public class AppConfig {
//includeFilters 替换成 ExcludeFilter,就算它上面有@Component注解也不会成为Bean。    

获取类的元数据

SimpleMetadataReader去解析类时,使用的ASM技术

ASM是一个Java字节码操作和分析框架,全称是A Java bytecode manipulation and analysis framework。

MetadataReader

ClassMetadata

AnnotationMetadata

@Test
    void metadata() {
        var factory = new SimpleMetadataReaderFactory();
        try {
            MetadataReader metadataReader = factory.getMetadataReader("com.lywtimer.service.CourseService");

            // 得到一个ClassMetadata,并获取了类名
            ClassMetadata classMetadata = metadataReader.getClassMetadata();
            System.out.println(classMetadata.getClassName());
            System.out.println(Arrays.toString(classMetadata.getInterfaceNames()));

            // 获取一个AnnotationMetadata,并获取类上的注解信息
            AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
            for (String annotationType : annotationMetadata.getAnnotationTypes()) {
                System.out.println(annotationType);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值