Tiny-Spring——生命周期、三级缓存、类型转换

详情请见 https://github.com/StrongChenYu/Tiny-Spring

1. 生命周期

总体来说是先refresh() => getBean()

1.1 refresh
  1. 调用refreshBeanFactory => loadBeanDefinition将会把创建所有的BeanDefinition =》 doScan =》 扫描包中所有注解@Component
  2. addApplicationContextAwareProcessor => 要在ApplicationContextAwareProcessor中添加ApplicatoinContext本身
  3. invokeBeanFactoryPostProcessors,调用beanFactoryPostProcessor => PropertyPlaceholderConfigurer(BeanFactoryPostProcessor) 将propertires中的所有属性,注入到BeanDefinition中 诸如此类:${value}
  4. registerBeanPostProcessors, factory.addBeanPostProcessor
  5. beanFactory.preInstantiateSingletons() 这里会提前实例化所有的Bean
// 1. 创建 BeanFactory,并加载 BeanDefinition
// loadBeanDefinition 会调用doScan方法,主要是自动扫描包中的所有类,
// 然后把类的信息映射到beanDefinition中
refreshBeanFactory(); => loadBeanDefinition() => doScan()

// 2. 获取 BeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();

// 3. 添加 ApplicationContextAwareProcessor,让继承自 ApplicationContextAware 的 Bean 对象都能感知所属的 ApplicationContext
// Aware的东西主要发生在getBean()的时候,注入ApplicationContext,而ApplicationContext对象需要在这个上下文获取
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

// 4. 在 Bean 实例化之前,执行 BeanFactoryPostProcessor (Invoke factory processors registered as beans in the context.)
// 这个阶段执行beanFactoryProcessor
invokeBeanFactoryPostProcessors(beanFactory);

// 5. BeanPostProcessor 需要提前于其他 Bean 对象实例化之前执行注册操作
registerBeanPostProcessors(beanFactory);

// 6. 初始化事件发布者
initApplicationEventMulticaster();

// 7. 注册事件监听器
registerListeners();

// 8. 提前实例化单例Bean对象
// !!!!!!!!这里会调用所有bean的getBean方法,会预先实例化所有的bean,关于getBean会完成哪些事情,看下面
beanFactory.preInstantiateSingletons();

// 9. 发布容器刷新完成事件
finishRefresh();
1.2 getBean

getBean周期如下:

  1. Invoke InstantiationAwareBeanPostProcessor() 在创建类之前运行的PostProcessor(method postProcessBeforeInstantiation)

  2. createBeanInstance => cglib或者其他方式调用bean的construct method

  3. applyBeanPostProcessorBeforeApplyPropertyValues() 这个步骤会去解析@Value注解,@Autowired注解,@Qualifier注解,主要是为了把beanDefinition中的PropertyValues设置成相应的依赖值

  4. applyPropertyValues 将BeanDefinition中的propertyValues设置到bean中

  5. 调用initializeBean方法。=》5.1 调用injectAwareBean中的set方法,把相应的aware设置到对象中

    5.2 applyBeanPostProcessorBeforeInitialization
    5.3 调用@Init-method方法
    5.4 调用applyBeanPostProcessorAfterInitialization (这个阶段会调用代理对象的创建方法DefaultAdvisorAutoProxyCreator)

protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException {
    Object bean = null;

    try {
        bean = resolveBeforeInstantiation(beanName, beanDefinition);
        if (bean != null) {
            // 这里是不是需要处理一些东西,填充属性
            return bean;
        }

        //create bean
        bean = createBeanInstance(beanDefinition, beanName, args);

        // 在apply之前把自动注入的属性都加入到properties中
        applyBeanPostProcessorsBeforeApplyPropertyValues(beanName, bean, beanDefinition);

        //support bean property
        applyPropertyValues(beanName, bean, beanDefinition);

        bean = initializeBean(beanName, bean, beanDefinition);
    } catch (Exception e) {
        throw new BeansException("Instantiation of bean failed", e);
    }

    if (beanDefinition.isSingleton()) {
        addSingleton(beanName, bean);
    }
    return bean;
}
private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) {
    //注入aware对象
    injectAwareBean(beanName, bean, beanDefinition);

    //前置处理
    Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);

    //调用初始化方法
    try {
        invokeInitMethods(beanName, wrappedBean, beanDefinition);
    } catch (Exception e) {
        throw new BeansException("Invocation of init method of bean[" + beanName + "] failed", e);
    }

    //后置处理
    wrappedBean = applyBeanPostProcessorsAfterInitialization(bean, beanName);

    return wrappedBean;
}

2. 三级缓存

Spring三级缓存目的主要为了解决循环依赖的问题。(本身的SingletonBeanRegistry使用的就是一级缓存)
一级缓存实际上已可解决循环依赖,解决方式如下:
在这里插入图片描述

这样做的缺点就是这样会导致,下面这个单例的保存Map里面,会保存着两种类型的副本:

  1. 调用了构造方法,但未进行属性填充的Bean。(造成这种情况的原因是调用ApplyBeanPropertyValue的过程中跳入到了别的getBean方法)
  2. 调用了构造方法,也进行了属性填充的Bean。
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {

    private final Map<String, Object> singleObjects = new ConcurrentHashMap<>();
    private final Map<String, DisposableBean> disposableBeans = new ConcurrentHashMap<>();
    protected static final Object NULL_OBJECT = new Object();
}

所以,根据单一职责原则,将上面提到的两种bean放到两个不同的map中,
调用了构造方法,但未进行属性填充的Bean,放到二级缓存中
调用了构造方法,也进行了属性填充的Bean,放到一级缓存中。

新的问题:代理对象怎么办?

因为如果遵循上面的解决方案的话,如果这样放的话,代理对象是在postProcessor中代理的,处理之后的bean不会实时的更新到一级缓存中,相当于没有进行了代理。
解决方案:
在这里插入图片描述

这种方式即可解决代理对象带来的问题
但是还是那个原则:单一职责原则
所以又增加了一级缓存专门存放代理对象。总的来说,缓存就被划分成了以下几个层次。

  1. 一级缓存:完全实例化的对象
  2. 二级缓存:只调用了构造方法的对象。
  3. 三级缓存:被代理的对象

3. 数据类型转换

这部分主要是围绕三个接口

public interface Converter<S, T>  {
    T convert(S source);
}
public interface ConverterFactory<S, R>{
    <T extends R> Converter<S, T> getConverter(Class<T> targetType);
}

public interface GenericConverter {
    Set<ConvertiblePair> getConvertibleTypes();
    Object convert(Object source, Class sourceType, Class targetType);
}
设计模式
  1. 工厂方法模式
  2. 适配器模式
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值