02 Spring整体脉络(顶层接口)

1 回顾:使用springIOC的流程

在这里插入图片描述

  1. 使用spring的时候,可以通过两种方式:xml配置和注解驱动的方式;
  2. 最终通过ApplicationContext从ioc容器中就可以通过getBean的方式(通过BeanFactory的getBean的)生产 Bean

    getBean其实是生产Bean,并非是获取Bean,而是根据我们的配置给我们生产Bean,只是spring做了一层缓存,看起来像是获取获取Bean

这里就有一个问题xml和注解驱动是通过不同的方式(ClassPathXmlApplicationContext,AnnotationConfigApplicationContext)来获取Bean;虽然使用的类不同,但是无论我们哪种方式配置肯定是要读取成一个统一的方式啊,交给BeanFactory来生产BeanBean(解耦)

2 springIOC的整体脉络

2.1 Bean定义( BeanDefinition)

在这里插入图片描述

无论是注解驱动还是xml最终都会将这些配置,读取成一个个的Bean定义( BeanDefinition);

org.springframework.beans.factory.config.BeanDefinition是spring的一个顶层接口

可以看一下他的一个抽象实现org.springframework.beans.factory.support.AbstractBeanDefinition

// 部分代码展示
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
		implements BeanDefinition, Cloneable {
	// 当前bean的class类型
	@Nullable
	private volatile Object beanClass;
	private boolean primary = false;
	@Nullable
	private String scope = SCOPE_DEFAULT;
	
	@Nullable
	private String initMethodName;
	
	@Nullable
	private String destroyMethodName;
	@Nullable
	private Boolean lazyInit;
}

发现这抽线实现里面定义了许多我们在配置Bean的时候可以配置的选项(scope,initinitMethod,primary,是不是懒加载。。。)

spring会把这些bean定义最终存到一个Map里面

既然有个这个统一的Bean定义,那么就需要知道如何将这些Bean定义收集起来了?

2.2 注册Bean定义(BeanDefinitionRegistry)

如何将我们的Bean定义收集起来了?

就通过这个接口org.springframework.beans.factory.support.BeanDefinitionRegistry

其中就声明了这么一个方法,注册BeanDefinition:

void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
		throws BeanDefinitionStoreException;

这个接口还有其他的方法声明,比如removeBeanDefinition(删除Bean定义);

AnnotationConfigApplicationContext就实现了这个接口

就通过这个registerBeanDefinition将一个个的Bean定义最终注册(收集到)一个Map中

这个接口只是注册Bean定义,显然还需要一个组件将我们的xml或者配置类读取为Bean定义;
不仅仅还有读取,我们通常还会配置扫描的包,只会扫描这个包下带有@Component这种注解的Bean才会最终被Spring管理

2.3 BeanDefinitionReader和ClassPathBeanDefinitionScanner

这两个组件就是负责读取和扫描

在这里插入图片描述

2.3 生产Bean的大致流程

Bean定义已经处理完成之后,当我们调用getBean的时候就会生产Bean,就会发生一下大概的几个流程

  1. 实例化,可以通过反射(比如xml配置的时候就是通过反射)或者new(配置类中往往就是通过new)

  2. 接下来就是填充属性,比如通过@Autowired; @Value等注解注入的属性

  3. 如果配置了init方法就会去调用我们配置的初始化方法

  4. 如果配置了销毁方法,当Bean销毁的时候就会调用对应的销毁方法

  5. 最终会将这个Bean放到一个Map中(单例池),一级缓存

在这里插入图片描述

3 spring中的扩展点

上面介绍了大致的流程,这些流程中还内置了很多扩展点,spring的生态为何如此牛逼,就是因为这些扩展点的存在,让其他框架都可以与之整合

3.1 Bean定义的核心扩展点

3.1.1 修改Bean定义:BeanFactoryPostProcessor
package org.springframework.beans.factory.config;
@FunctionalInterface
public interface BeanFactoryPostProcessor {

	/**
	 * Modify the application context's internal bean factory after its standard
	 * initialization. All bean definitions will have been loaded, but no beans
	 * will have been instantiated yet. This allows for overriding or adding
	 * properties even to eager-initializing beans.
	 * @param beanFactory the bean factory used by the application context
	 * @throws org.springframework.beans.BeansException in case of errors
	 */
	 /**
	  All bean definitions will have been loaded, but no beans: 
	  说明这个方法执行的时候所有的Bean definition已经加载,但是没有生产Bean
	 **/
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

eg:

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    /**
     * 形参就是bean工厂
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // 根据beanName获取某个bean定义
        BeanDefinition user = beanFactory.getBeanDefinition("user");
        System.out.println(user.getBeanClassName());
        // 修改这个bean定义中的BeanClassName
        user.setBeanClassName("java.lang.String");
    }
    
}
3.1.2 注册Bean定义:BeanDefinitionRegistryPostProcessor
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

	/**
	 * Modify the application context's internal bean definition registry after its
	 * standard initialization. All regular bean definitions will have been loaded,
	 * but no beans will have been instantiated yet. This allows for adding further
	 * bean definitions before the next post-processing phase kicks in.
	 * @param registry the bean definition registry used by the application context
	 * @throws org.springframework.beans.BeansException in case of errors
	 */
	void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}

形参就是BeanDefinitionRegistry,就可以通过这个BeanDefinitionRegistry注册BeanDefinition;

mybatis和spring的整合就是通过这个去实现的

扫描Bean和配置类都是通过BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor实现的

在这里插入图片描述

3.2 Bean的生命周期中的扩展点

在实例化,填充属性的时候都有系列的BeanPostProcessor,来扩展我们的Bean

一共会调用9此BeanPostProcessor

这里就先不多介绍

4 BeanFactory和ApplicationContext的区别

  1. ApplicationContext中的getBean也是调用BeanFactory的getBean
  2. BeanFactory就是个工厂,根据Bean定义生产Bean
  3. ApplicationContext是面向用户的,不仅仅要提供Bean和调用工厂去生成Bean,还要提供一系列的其他功能(如果国际化,加载Bean定义等等)
  4. ApplicationContext是依赖BeanFactory,没有BeanFactory就无法生成Bean
// ApplicationContext
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
assertBeanFactoryActive();
	return getBeanFactory().getBean(name, requiredType);
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值