Tiny-Spring——ApplicationContext系列

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

1. 为什么要有ApplicationContext

ApplicationContext主要是为了将以下几个步骤(当然源spring中可能有更多)整合起来,放到一个容器中,提供生命周期管理。

  1. xml文件,进行bean的读取和beanDefinition的读取
  2. 注册postProcessor
  3. 注册BeanFactoryPostProcessor
  4. invoke BeanFactoryPostProcessor

如果不经过ApplicationContext,那么这一系列的过程大概是这样的,需要自己手动去注册路径,注册postprocessor等一系列的操作。

@Test
public void testBeanFactoryPostProcessorAndBeanPostProcessor() {
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
    reader.loadBeanDefinition("classpath:spring.xml");

    BeanFactoryPostProcessor myBeanFactoryPostProcessor = (BeanFactoryPostProcessor) factory.getBean("myBeanFactoryPostProcessor");
    myBeanFactoryPostProcessor.postProcessBeanFactory(factory);

    factory.addBeanPostProcessor((BeanPostProcessor) factory.getBean("myBeanPostProcessor"));

    UserService userService = factory.getBean("userService", UserService.class);

    System.out.println(userService);

}

而有了ApplicationContext后,这一系列的操作都被整合到ApplicationContextrefresh方法中了。

@Test
public void testXML() {
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
    applicationContext.registerShutdownHook();

    UserService userService = applicationContext.getBean("userService", UserService.class);
    System.out.println("测试结果:" + userService);
}

2. ApplicationContext的结构

大概这个样子

在这里插入图片描述

继承:ApplicationContext的一系列继承
组合:组合DefaultListableBeanFactory,主要用于委托接口中的功能。

3. ApplicationContext中需要实现的各个部分

整体就是refresh中的九个步骤

public void refresh() throws BeansException {
    // 1. 加载BeanDefinition
    refreshBeanFactory();
    // 2. 获取beanFactory
    ConfigurableListableBeanFactory factory = getBeanFactory();
    // 3. 添加ApplicationContextAwareProcessor
    factory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    // 4. 调用factoryPostProcessor
    invokeBeanFactoryPostProcessor(factory);
    // 5. 注册beanPostProcessor
    registerBeanPostProcessor(factory);
    // 6. 初始化事件
    initApplicationEventMulticaster();
    // 7. 注册listener
    registerListener();
    // 8. 这里会把所有的bean全部调用一次getBean方法
    factory.preInstantiateSingletons();
    // 9. finish
    finishRefresh();
}

一些具体的实现

3.1 FactoryBean

**FactoryBean****BeanFactory**的区别
BeanFactory是用来生成Bean和管理Bean
FactoryBean也属于Bean
如果容器getBean时发现是一个FactoryBean,就会去调用FactoryBeangetObject方法。
这样做有什么用途呢?
一个实际的案例就是Mybatis中,利用FactoryBeanservice层的对象自动提供代理
在调用servicecreateBean时,去get具体的ORM对象时,会调用他的getObject方法。

3.2 ResourceLoader

XmlBeanDefinitionReader组合,从xml中解析bean对象
XmlBeanDefinitionReaderResourceLoader组合,加载流并且获取流
ResourceLoader的类结构
在这里插入图片描述
![6f9066b0befd2560ecb35b6deb60b47.jpg](https://img-blog.csdnimg.cn/img_convert/c19df4d6ac10e41d99170a265260f395.png#clientId=ubefb3246-44b9-4&from=drop&height=270&id=u7dfbe160&margin=[object Object]&name=6f9066b0befd2560ecb35b6deb60b47.jpg&originHeight=1080&originWidth=1440&originalType=binary&ratio=1&size=61846&status=done&style=none&taskId=uf750b49c-c8e9-43cd-a459-c3f1b9c184a&width=360)

3.3 Event and listener

这部分通过定义了一个ApplicationContextMulticaster对象用来管理和通知listener
如果有event发生
通过application.publishEvent方式
那么就会通过ApplicationContextMulticaster对象通知所有的listenerlistener检查是不是自己的event
主要通过检查泛型类是否和event一样
然后调用listener的响应的方法。

3.4 Aware

Aware的作用是给bean提供了一个可以反向利用Spring framework中组件的机会,他会在getBean中的createBean方法中判断bean需要哪一个类型的aware,然后调用相应的set方法,将容器中的组件set进去,大概像是这个样子(反射)

private void invokeAwareInterfaces(Object bean) {
    if (bean instanceof EnvironmentAware) {
        ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
    }
    if (bean instanceof EmbeddedValueResolverAware) {
        ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
    }
    if (bean instanceof ResourceLoaderAware) {
        ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
    }
    if (bean instanceof ApplicationEventPublisherAware) {
        ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
    }
    if (bean instanceof MessageSourceAware) {
        ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
    }
    if (bean instanceof ApplicationStartupAware) {
        ((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
    }
    if (bean instanceof ApplicationContextAware) {
        ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
    }
}

4. 总结

4.1 设计模式
  • 经典的模板方法模式。(严格意义上来说不算是模板方法模式,只是把各个功能分层,不同的实现放到了不同的抽象类中。
  • 委托模式ApplicationContext也继承自BeanFactory,但他的关于这部分的方法实现委托给了同样实现了该相关接口的DefaultListableBeanFactory。但是ApplicationContext实现ListableBeanFactory二层子接口,但是DefaultListableBeanFactory实现了三个二层子接口,为什么还能委托? 我感觉到就是这种模式的精妙之处,只把自己需要的部分委托出去。(有深意,注意理解)。
  • 适配器模式DisposableBeanAdapter(这个的作用是,将disposableBeandestoryMethod中的统一到一个adpater中,然后容器统一去处理这个adpater
  • 观察者模式。事件处理(使用经典的观察者模式)multicaster相当于subjectlistener相当于订阅者,至于两者的绑定是在容器中的refresh中进行的。(get所有typeapplicationListenerbean,然后绑定)
4.2 接口的继承

慢慢体会到,接口这样分层的目的,可以起到控制权限的作用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值