【源码Spring系列】——Spring中核心概念

  1. BeanDefinition
    Spring中定义bean的方式
 @Bean
 @Component
 <bean/>

还可以通过BeanDefinition来定义一个bean

 DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        //定义一个bean
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
        beanDefinition.setBeanClass(CouponAuditDO.class);
        //设置其他属性
        beanDefinition.setScope("prototype");
        beanDefinition.setInitMethodName("init"); // 设置初始化方法
        beanDefinition.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE); // 设置自动装配模型
        //将BeanDefinition注册到BeanFactory中
        beanFactory.registerBeanDefinition("couponAuditDo", beanDefinition);

        // 获取Bean
        System.out.println(beanFactory.getBean("couponAuditDo"));

通过,@Bean,@Component等方式所定义的Bean,最终都会被解析为BeanDefinition对象。
BeanDefinition可以理解为底层源码级别的一个概念,也可以理解为Spring提供的一种API使用的方式。


  1. BeanDefinitionReader
    将bean解析转换成BeanDefinition,BeanDefinitionReader分为几类:

2.1 AnnotatedBeanDenfinitionReader
可以直接将某个类转换成BeanDefinition,并且解析该类上的注解
它能解析的注解是:@Conditional,@Scope、@Lazy、@Primary、@DependsOn、@Role、@Description

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(beanFactory);
// 将User.class解析为BeanDefinition
annotatedBeanDefinitionReader.register(User.class);
System.out.println(beanFactory.getBean("user"));

2.2 XmlBeanDenfinitionReader
可以解析Spring.xml中bean标签

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

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

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


  1. BeanFactory
    Spring中比较核心的是BeanFactory的实现类是DefaultListableBeanFactory
    DefaultListableBeanFactory
  • AliasRegistry:支持别名功能,一个名字可以对应多个别名
  • BeanFactory:bean工厂,根据bean的类型,名字,别名获取对应的bean
  • SingletonBeanRegistry:注册,获取某个单例bean
  • SimpleAliasRegistry:实现AliasRegistry中定义的所有功能,支持别名功能
  • BeanDefinitionRegistry:注册,保存,移除,获取某个BeanDefinition
  • ListableBeanFactory:在beanFactory的基础上增加了可以获取所有BeanDefinition的beanNames,根据某个类型获取对应的beanNames,可以根据某个类型获取{类型:对应的Bean}的映射关系
  • HierarchicalBeanFactory:在beanFactory的基础,增加获取父类在beanFactory的功能
  • DefaultSingletonBeanRegistry:实现SingletonBeanRegistry中所有功能,同时支持别名功能
  • FactoryBeanRegistrySupport:支持FactoryBean功能
  • ConfigurableBeanFactory:增加设置父类BeanFactory,类加载器,设置Spring EL表达式解析器,设置类型转化服务,添加BeanPostProcessor,可以合并BeanDefinition,可以销毁某个bean等功能
  • AbstractBeanFactory:实现了ConfigurableBeanFactory,并继承FactoryBeanRegistrySupport
  • AutowireCapableBeanFactory:在BeanFactory基础上,支持在创建bean的过程中对bean进行自动装配
  • AbstractAutowireCapableBeanFactory:继承了AbstractBeanFactory,实现了AutowireCapableBeanFactory,拥有了自动装配的功能
  • ConfigurableListableBeanFactory:继承了ListableBeanFactory、AutowireCapableBeanFactory、ConfigurableBeanFactory
  • DefaultListableBeanFactory:继承了AbstractAutowireCapableBeanFactory,实现了ConfigurableListableBeanFactory接口和BeanDefinitionRegistry接口,所以DefaultListableBeanFactory的功能很强大

  1. ApplicationContext
    ApplicationContext是个接口,可以把它理解为一个特殊的BeanFactory
    ApplicationContext
  • ListableBeanFactory:可以获取beanNames
  • HierarchicalBeanFactory:可以获取父BeanFactory
  • ResourcePatternResolver:资源加载器,可以一次性获得多个资源(文件资源)
// 获取某个文件的内容
Resource resource = annotationConfigApplicationContext.getResource("file://D:\\spring-framework\\src\\main\\java\\com\\mandy\\entity\\User.java");
System.out.println(resource.contentLength());

还支持一次性获取多个

Resource[] resources = annotationConfigApplicationContext.getResources("classpath:com/mandy/service/*.class");
for (Resource resource : resources) {
	System.out.println(resource.contentLength());
}
  • EnvironmentCapable:获取运行时环境
// 获取JVM所允许的操作系统的环境
annotationConfigApplicationContext.getEnvironment().getSystemEnvironment();

// 获取JVM本身的一些属性,包括-D所设置的
annotationConfigApplicationContext.getEnvironment().getSystemProperties();

// 还可以直接获取某个环境或properties文件中的属性
annotationConfigApplicationContext.getEnvironment().getProperty("test")
//还可以利用注解的方式
@PropertySource("classpath:application.properties")
  • MessageSource:拥有国际化功能
@Bean
public MessageSource messageSource() {
    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    messageSource.setBasename("messages");
    return messageSource;
}
applicationContext.getMessage("test", null, new Locale("en_CN"))
  • ApplicationEventPublisher:拥有广播事件的功能
// 定义一个事件监听器
@Bean
public ApplicationListener applicationListener() {
    return new ApplicationListener() {
        @Override
        public void onApplicationEvent(ApplicationEvent event) {
            System.out.println("接收到了一个事件");
        }
    };
}
//发布一个事件
applicationContext.publishEvent("kkk");

两个比较重要的实现类
4.1、ClassPathXmlApplicationContextClassPathXmlApplicationContext

  • ConfigurableApplicationContext:继承了ApplicationContext接口,增加了,添加事件监听器、添加BeanFactoryPostProcessor、设置Environment,获取ConfigurableListableBeanFactory等功能
  • AbstractApplicationContext:实现了ConfigurableApplicationContext接口

4.2、AnnotationConfigApplicationContext
AnnotationConfigApplicationContext
相比ClassPathXmlApplicationContext支持的功能继续增加,而且拥有了BeanDefinitionRegistry功能

  • GenericApplicationContext:继承了AbstractApplicationContext,实现了BeanDefinitionRegistry接口,拥有了所有ApplicationContext的功能,并且可以注册BeanDefinition,注意这个类中有一个属性(DefaultListableBeanFactory
    beanFactory)
  • AnnotationConfigRegistry:可以单独注册某个为类为BeanDefinition(可以处理该类上的@Configuration注解,已经可以处理@Bean注解),同时可以扫描
  • AnnotationConfigApplicationContext:继承了GenericApplicationContext,实现了AnnotationConfigRegistry接口,拥有了以上所有的功能

5.类型转换
举例使用场景,利用xml定义bean时,bean中属性的注入,即便是Integer类型,但是书写的是也是使用string类型,那么其中的转换则是由类型转换完成的

<bean id="dingTalkAlarm" class="com.xxx.common.business.alarm.DingTalkAlarm">
        <constructor-arg name="title" value="业务通知"/>
        <constructor-arg name="num" value="${noticenum}"/>
</bean>
  • PropertyEditor
    JDK中提供的类型转换工具类
public class StringToUserPropertyEditor extends PropertyEditorSupport implements PropertyEditor {

	@Override
	public void setAsText(String text) throws IllegalArgumentException {
		User user = new User();
		user.setName(text);
		this.setValue(user);
	}
}
StringToUserPropertyEditor propertyEditor = new StringToUserPropertyEditor();
propertyEditor.setAsText("1");
User value = (User) propertyEditor.getValue();
System.out.println(value);

如何向Spring中注册PropertyEditor:

@Bean
public CustomEditorConfigurer customEditorConfigurer() {
    CustomEditorConfigurer customEditorConfigurer = new CustomEditorConfigurer();
    Map<Class<?>, Class<? extends PropertyEditor>> propertyEditorMap = new HashMap<>();
    propertyEditorMap.put(User.class, StringToUserPropertyEditor.class);
    customEditorConfigurer.setCustomEditors(propertyEditorMap);
    return customEditorConfigurer;
}
  • ConversionService
    Spring中提供的类型转化服务,它比PropertyEditor更强大
public class StringToUserConverter implements ConditionalGenericConverter {
    @Override
    public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
        return sourceType.getType().equals(String.class) && targetType.getType().equals(User.class);
    }
    @Override
    public Set<ConvertiblePair> getConvertibleTypes() {
        return Collections.singleton(new ConvertiblePair(String.class, User.class));
    }
    @Override
    public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
        User user = new User();
        user.setName((String)source);
        return user;
    }
}
DefaultConversionService conversionService = new DefaultConversionService();
conversionService.addConverter(new StringToUserConverter());
User value = conversionService.convert("1", User.class);
System.out.println(value);

如何向Spring中注册ConversionService:

@Bean
public ConversionServiceFactoryBean conversionService() {
    ConversionServiceFactoryBean conversionServiceFactoryBean = new ConversionServiceFactoryBean();
    conversionServiceFactoryBean.setConverters(Collections.singleton(new StringToUserConverter()));
    return conversionServiceFactoryBean;
}
  • TypeConverter
    整合了PropertyEditor和ConversionService的功能,是Spring内部用的
SimpleTypeConverter typeConverter = new SimpleTypeConverter();
typeConverter.registerCustomEditor(User.class, new StringToUserPropertyEditor());
//typeConverter.setConversionService(conversionService);
User value = typeConverter.convertIfNecessary("1", User.class);
System.out.println(value);

6.BeanPostProcessor
Bean的后置处理器,可以在创建每个Bean的过程中进行干涉,是属于BeanFactory中一个属性,在之后详情深入


  1. BeanFactoryPostProcessor
    Bean工厂的后置处理器,是属于ApplicationContext中的一个属性,是ApplicationContext在实例化一个BeanFactory后,可以利用BeanFactoryPostProcessor继续处理BeanFactory。

可以通过BeanFactoryPostProcessor间接的设置BeanFactory,比如上文中的CustomEditorConfigurer就是一个BeanFactoryPostProcessor,我们可以通过它向BeanFactory中添加自定义的PropertyEditor。


  1. FactoryBean
    关于FactoryBean在之前的文章中讲过《FactoryBean与BeanFactory不同》简单来说,允许自定义一个对象通过FactoryBean间接放到Spring容器中成为bean,补充之前文章缺少知识点
    FactoryBean和@Bean有何不同?
    @Bean也可以自定义一个对象,让这个对象成为一个Bean。
    区别在于利用FactoryBean可以更加强大,因为你通过定义一个XxFactoryBean的类,可以再去实现Spring中的其他接口,比如如果你实现了BeanFactoryAware接口,那么你可以在你的XxFactoryBean中获取到Bean工厂,从而使用Bean工厂做更多你想做的,而@Bean则不行。
    整体来说就是相比FactoryBean,@Bean的功能过于单一了。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mandy_i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值