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);
}
}