spring5.3 源码学习二

spring5.3 核心类学习

本次学习spring源码中一些重要的类和概念,对后续源码学习很有帮助

BeanDefinition

BeanDefinition是一个接口,表示Bean定义,BeanDefinition中存在很多属性用来描述一个Bean性质。比如

  1. class :表示bean的类型
  2. scope:表示bean作用域,单例或者原型
  3. lazyint:表示懒加载
    。。。。。等等

在spring中经常我们通过,@Bean,@controller等方式创建bean,这些称为声明式定义bean。我们也可以通过编程式定义bean,通过BeanDefinition定义

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(GoodsService.class);
context.registerBeanDefinition("goodsService",beanDefinition);
beanDefinition.setScope("prototype"); // 设置作用域
beanDefinition.setInitMethodName("init"); // 设置初始化方法
beanDefinition.setLazyInit(true); // 设置懒加载
GoodsService goodService = context.getBean("goodsService", GoodsService.class);

下面介绍几种BeanDefinition的读取器BeanDefinitionReader,这些BeanDefinitionReader在我们使用spring时用的少,但是在spring源码中经常使用,相当于spring的基础设施

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

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(context);
reader.register(GoodsService.class);
GoodsService goodsService = context.getBean("goodsService", GoodsService.class);

注意:它能解析的注解是:@Conditional,@Scope、@Lazy、@Primary、@DependsOn、 @Role、@Description
XmlBeanDefinitionReader
用来解析xml的配置

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

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

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); 
context.refresh(); 
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); scanner.scan("com.mydemo"); 
System.out.println(context.getBean("goodsService"));

BeanFactory
BeanFactory负责创建Bean,并提供获取bean的API。而ApplicationContext是BeanFactory的一种,在Spring源码中,是这么定义的:

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
		MessageSource, ApplicationEventPublisher, ResourcePatternResolver {

我们发现ApplicationContext继承了ListableBeanFactory 和HierarchicalBeanFactory,而ListableBeanFactory和HierarchicalBeanFactory都继承 BeanFactory。因此ApplicationContext也是BeanFactory的一种,拥有BeanFactory支持的所有功 能,不过ApplicationContext比BeanFactory更加强大,ApplicationContext还继承了其他接口,也 就表示ApplicationContext还拥有其他功能,比如MessageSource表示国际化, ApplicationEventPublisher表示事件发布,EnvironmentCapable表示获取环境变量等
在spring源码中,当我们new一个ApplicationContext,其底层就会new一个BeanFactory,当我们调用getBean方法,底层调用的是BeanFactory的getBean()方法。
DefaultListableBeanFactory
在spring源码中BeanFactory接口存在一个非常重要的实现类DefaultListableBeanFactory。spring源码中DefaultListableBeanFactory的定义

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

所以我们可以直接使用DefaultListableBeanFactory替代ApplicationContext的实现类

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
		AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(GoodsService.class);
beanFactory.registerBeanDefinition("goodsService",beanDefinition);
System.out.println(beanFactory.getBean("goodsService",GoodsService.class));

在这里插入图片描述

通过查看 DefaultListableBeanFactory的类继承实现结构来看,DefaultListableBeanFactory是非常强大的。
它实现了很多接口,表示它拥有很多功能:

  1. AliasRegistry:支持别名功能,一个名字可以对应多个别名
  2. BeanDefinitionRegistry:可以注册、保存、移除、获取某个BeanDefinition
  3. BeanFactory:Bean工厂,可以根据某个bean的名字、或类型、或别名获取某个Bean对象
  4. SingletonBeanRegistry:可以直接注册、获取某个单例Bean
  5. SimpleAliasRegistry:它是一个类,实现了AliasRegistry接口中所定义的功能,支持别名功能
  6. ListableBeanFactory:在BeanFactory的基础上,增加了其他功能,可以获取所有 BeanDefinition的beanNames,可以根据某个类型获取对应的beanNames,可以根据某个类 型获取{类型:对应的Bean}的映射关系
  7. HierarchicalBeanFactory:在BeanFactory的基础上,添加了获取父BeanFactory的功能
  8. DefaultSingletonBeanRegistry:它是一个类,实现了SingletonBeanRegistry接口,拥有了直 接注册、获取某个单例Bean的功能
  9. ConfigurableBeanFactory:在HierarchicalBeanFactory和SingletonBeanRegistry的基础上, 添加了设置父BeanFactory、类加载器(表示可以指定某个类加载器进行类的加载)、设置 Spring EL表达式解析器(表示该BeanFactory可以解析EL表达式)、设置类型转化服务(表示 该BeanFactory可以进行类型转化)、可以添加BeanPostProcessor(表示该BeanFactory支持 Bean的后置处理器),可以合并BeanDefinition,可以销毁某个Bean等等功能
  10. FactoryBeanRegistrySupport:支持了FactoryBean的功能
  11. AutowireCapableBeanFactory:是直接继承了BeanFactory,在BeanFactory的基础上,支持 在创建Bean的过程中能对Bean进行自动装配
  12. AbstractBeanFactory:实现了ConfigurableBeanFactory接口,继承了 FactoryBeanRegistrySupport,这个BeanFactory的功能已经很全面了,但是不能自动装配和 获取beanNames
  13. ConfigurableListableBeanFactory:继承了ListableBeanFactory、 AutowireCapableBeanFactory、ConfigurableBeanFactory
  14. AbstractAutowireCapableBeanFactory:继承了AbstractBeanFactory,实现了 AutowireCapableBeanFactory,拥有了自动装配的功能
  15. DefaultListableBeanFactory:继承了AbstractAutowireCapableBeanFactory,实现了 ConfigurableListableBeanFactory接口和BeanDefinitionRegistry接口

ApplicationContext
之前有提到过ApplicationContext,功能比BeanFactory要强大

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
		MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
  1. HierarchicalBeanFactory:拥有获取父BeanFactory的功能
  2. ListableBeanFactory:拥有获取beanNames的功能
  3. ResourcePatternResolver:资源加载器,可以一次性获取多个资源(文件资源等等) 、
  4. EnvironmentCapable:可以获取运行时环境(没有设置运行时环境功能)
  5. ApplicationEventPublisher:拥有广播事件的功能(没有添加事件监听器的功能)
  6. MessageSource:拥有国际化功能

ApplicationContext两个重要实现类:1. AnnotationConfigApplicationContext 2. ClassPathXmlApplicationContext

AnnotationConfigApplicationContext
在这里插入图片描述

ClassPathXmlApplicationContext
在这里插入图片描述
获取运行时环境

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("================================");

可以利用@PropertySource("classpath:spring.properties")将某个properties的参数加入到运行时环境中

事件发布
定义一个事件监听器

@Bean
public ApplicationListener listerner(){
	return new ApplicationListener(){
		@Override
		public void onApplicationEvent(ApplicationEvent event) {
			System.out.println("接受到一个事件");
		}
	};
}
//Test
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
context.publishEvent("test");

国际化
定义国际化资源文件
在这里插入图片描述

//定义bean
@Bean
public MessageSource messageSource(){
	ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
	messageSource.setBasename("message");
	return messageSource;
}
//Test
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
String test = context.getMessage("test", null, new Locale("en_US"));
System.out.println(test);

其他重要组件

类型转换

ConversionService
spring提供的类型转化服务。比如说要把一个goodsService类型转成UserService类型
常见类实现ConditionalGenericConverter

public class MyConversion implements ConditionalGenericConverter {
	//判断转换器的执行条件
	@Override
	public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
		//当来源类型符合GoodsService ,目标类型符合UserService 时使用该转化器,调用下面的convert 方法
		return sourceType.getType().equals(GoodsService.class) && targetType.getType().equals(UserService.class)
	}

	@Override
	public Set<ConvertiblePair> getConvertibleTypes() {
		return Collections.singleton(new ConvertiblePair(GoodsService.class, UserService.class));
	}

	//执行的方法
	@Override
	public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
		//具体转化的业务逻辑
		GoodsService goodsService = (GoodsService)source;
		String goodsName = goodsService.getGoodsName();
		UserService userService = new UserService();
		userService.setUserName(goodsName);
		return userService;
	}
}

//Test
DefaultConversionService conversionService = new DefaultConversionService();
conversionService.addConverter(new MyConversion());
GoodsService goodsService = new GoodsService();
goodsService.setGoodsName("商品名称");
UserService userService = conversionService.convert(goodsService, UserService.class);
System.out.println(userService);

在spring中使用:将conversionService注册到spring中

@Bean 
public ConversionServiceFactoryBean conversionService() { 
ConversionServiceFactoryBean conversionServiceFactoryBean = new ConversionServiceFactoryBean(); conversionServiceFactoryBean.setConverters(Collections.singleton(new MyConversion())); 
return conversionServiceFactoryBean; 
}

BeanPostProcessor
BeanPostProcess表示Bena的后置处理器,我们可以定义一个或多个BeanPostProcessor

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if ("userService".equals(beanName)){
			System.out.println("初始化前");
		}

		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if ("userService".equals(beanName)){
			System.out.println("初始化后");
		}

		return bean;
	}
}

一个BeanPostProcessor可以在任意一个Bean的初始化之前以及初始化之后去额外的做一些用户自 定义的逻辑,当然,我们可以通过判断beanName来进行针对性处理(针对某个Bean,或某部分 Bean)。

FactoryBean
上面提到,我们可以通过BeanPostPorcessor来干涉Spring创建Bean的过程,但是如果我们想由我们自己创建一个bean可以通过FactoryBean:

@Component
public class MyFactoryBean implements FactoryBean {
	@Override
	public Object getObject() throws Exception {
		UserService userService = new UserService();
		return userService;
	}

	@Override
	public Class<?> getObjectType() {
		return UserService.class;
	}
}

但是通过这种方式 创造出来的UserService的Bean,只会经过初始化后,其他Spring的生命周期步骤是不会经过的,比 如依赖注入。
实现FactoryBean接口会得到两个bean对象 一个是 getObject()返回的userService对象,一个是MyFactoryBean本身对象(放入单例池中),但是只会生成一个BeanDefinition。

MetadataReader、ClassMetadata、 AnnotationMetadata
在Spring中需要去解析类的信息,比如类名、类中的方法、类上的注解,这些都可以称之为类的元数据,所以Spring中对类的元数据做了抽象,并提供了一些工具类。
MetadataReader表示类的元数据读取器,默认实现类为SimpleMetadataReader

SimpleMetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader("com.mydemo.service.UserService");
ClassMetadata classMetadata = metadataReader.getClassMetadata();
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();

在这里插入图片描述
在这里插入图片描述

需要注意的是,SimpleMetadataReader去解析类时,使用的ASM技术。 为什么要使用ASM技术,Spring启动的时候需要去扫描,如果指定的包路径比较宽泛,那么扫描的 类是非常多的,那如果在Spring启动时就把这些类全部加载进JVM了,这样不太好,所以使用了 ASM技术。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值