[Spring手撸专栏学习笔记]——实现应用上下文

本文是《Spring 手撸专栏》第 7 章学习笔记,主要记录我的一些debug调试过程,方便后期复习。具体学习,大家可以去看一下这个专栏,强烈推荐。

什么是应用上下文?

感觉就是增强版的容器,不仅可以管理对象,还可以提供其他更多的服务,比如解析配置信息

BeanFactory与ApplicationContext

  • BeanFactory,这是最简单的容器,只能提供基本的DI功能;
  • 继承了BeanFactory后派生而来的应用上下文,其抽象接口也就是我们上面提到的的ApplicationContext,它能提供更多企业级的服务,例如解析配置文本信息等等,这也是应用上下文实例对象最常见的应用场景。
  • 应用上下文即是Spring容器抽象的一种实现;

今天我们要实现ClassPathXmlApplication,它可以从类路径下的一个或多个xml配置文件中加载上下文定义,适用于xml配置的方式;

设计

整体设计结构如下图:
在这里插入图片描述
● Spring 框架额外新增开发自己组建需求的两个必备接口: BeanFactoryPostProcess 和 BeanPostProcessor
● BeanFactoryPostProcessor,是由 Spring 框架组建提供的容器扩展机制,允许在 Bean 对象注册后但未实例化之前,对 Bean 的定义信息 BeanDefinition 执行修改操作。
● BeanPostProcessor,也是 Spring 提供的扩展机制,不过 BeanPostProcessor 是在 Bean 对象实例化之后修改 Bean 对象,也可以替换 Bean 对象。

同时上下文操作类要可以把相应的 XML 加载 、注册、实例化以及新增的修改和扩展都融合进去,让 Spring 可以自动扫描到我们的新增服务,便于用户使用

Spring 应用上下文和对Bean对象扩展机制的类关系

在这里插入图片描述

debug调试

起始

   public void test_xml() {
        // 1.初始化 BeanFactory (1)
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:springPostProcessor.xml");

        // 2. 获取Bean对象调用方法
        UserService userService = applicationContext.getBean("userService", UserService.class);
        String result = userService.queryUserInfo();
        System.out.println("测试结果:" + result);
    }

(1) ClassPathXmlApplicationContext 主线1
从XML中加载BeanDefinition,并刷新上下文


    public ClassPathXmlApplicationContext(String[] configLocations)throws BeansException{
        this.configLocations = configLocations;
        refresh();//(2)
    }

(2)AbstractApplicationContext 主线2
刷新上下文的具体方法

 public void refresh() throws BeansException {
        //1 创建BeanFactory,并加载BeanDefinition
        refreshBeanFactory();//(3)

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

        //3 在Bean实例化之前,执行BeanFactoryPostProcessor(调用在上下文中注册为bean的工厂处理器)
        invokeBeanFactoryPostProcessors(beanFactory);//(5)

        //4 BeanPostProcessor 需要提前于其他Bean对象实例化之前执行注册操作,会在这里
        //实例化MyBeanPostProcessor
        registerBeanPostProcessors(beanFactory);//(7)

        //5 提前实例化单例Bean对象,会在这里调用MyBeanPostProcessor修改新实例化 Bean 对象
        beanFactory.preInstantiateSingletons();//(9)


    }

(3) AbstractRefreshableApplicationContext
创建BeanFactory,并加载BeanDefinition的具体方法

 protected void refreshBeanFactory() throws BeansException {
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        loadBeanDefinitions(beanFactory); //(4)
        this.beanFactory = beanFactory;
    }

补充:
正是在这里,实现了自动初始化BeanFactory,并为其注册Bean。我们无需自己手动操作

(4)AbstractXmlApplicationContext
上下文对配置信息的加载的具体方法,主要是读取xml配置,加载BeanDefinition

补充1:
最终真正解析xml,加载bean定义,自动注册是在XmlBeanDefinitionReader的doLoadBeanDefinitions中

 protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory, this);
        String[] configLocations = getConfigLocations();
        if (null != configLocations){
            beanDefinitionReader.loadBeanDefinitions(configLocations);//补充1
        }
    }

(5) AbstractApplicationContext
在Bean实例化之前,执行我们子定义的MyBeanFactoryPostProcessor类,它实现了BeanFactoryPostProcessor接口

 private void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory){
      //根据类型来取BeanFactoryPostProcessor,在这里可以取到我们自定义的MyBeanFactoryPostProcessor类
     Map<String, BeanFactoryPostProcessor> beanFactoryPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
        for (BeanFactoryPostProcessor beanFactoryPostProcessor : beanFactoryPostProcessorMap.values()){
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);6}
    }

(6)MyBeanFactoryPostProcessor
具体的postProcessor操作

 public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");
        PropertyValues propertyValues = beanDefinition.getPropertyValues();
        propertyValues.addPropertyValue(new PropertyValue("company","改为:字节跳动"));
    }

(7) AbstractApplicationContext
BeanPostProcessor 需要提前于其他Bean对象实例化之前执行注册操作

注意这里beanFactory.getBeansOfType()会实例化我们的MyBeanPostProcessor

private void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory){
      //根据类型来取BeanPostProcessor,在这里可以取到我们自定义的postProcessor类   
     Map<String, BeanPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class);
        for (BeanPostProcessor beanPostProcessor : beanPostProcessorMap.values()){
            beanFactory.addBeanPostProcessor(beanPostProcessor);//(8)
        }
    }

(8) AbstractBeanFactory
注册BeanPostProcessor,将其添加进链表中

注意这里并没有调用我们自定义的MyBeanPostProcessor中的方法

//成员变量 
private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<BeanPostProcessor>();
 public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor){
        this.beanPostProcessors.remove(beanPostProcessor);
        this.beanPostProcessors.add(beanPostProcessor);
    }

(9)DefaultListableBeanFactory
这个类负责注册Bean定义与获取Bean定义

public void preInstantiateSingletons() throws BeansException {
        beanDefinitionMap.keySet().forEach(this::getBean);//(10)
  }

(10)AbstractBeanFactory
这个类负责对单例 Bean 对象的获取

public Object getBean(String name) throws BeansException{
        return doGetBean(name, null);//(11)
    }

(11)AbstractBeanFactory

protected <T> T  doGetBean(final  String name,final Object[] args){
        Object bean = getSingleton(name);
        if (bean != null){
            return (T) bean;
        }
        BeanDefinition beanDefinition = getBeanDefinition(name);
        return (T) creatBean(name,beanDefinition,args);//(12)
    }

(12)AbstractAutowireCapableBeanFactory
这个类主要负责实现了 Bean 的实例化
利用反射进行bean的实例化

protected Object creatBean(String beanName,BeanDefinition beanDefinition,Object[] args) throws BeansException {
       Object bean = null;
       try {
           bean = createBeanInstance(beanDefinition,beanName,args);
           //给Bean填充属性
           applyPropertyValues(beanName,bean,beanDefinition);
           //执行Bean 的初始化方法和BeanPostProcessor的前置和后置处理方法
           bean = initializeBean(beanName,bean,beanDefinition);//(13)
       } catch (Exception e) {
           throw new BeansException("Instantiation of bean failed",e);
       }

       addSingleton(beanName,bean);
        return bean;
    }

(13)AbstractAutowireCapableBeanFactory
执行Bean 的初始化方法和BeanPostProcessor的前置和后置处理方法

注意在这里才会调用MyBeanPostProcessor的方法

 private Object initializeBean(String beanName,Object bean,BeanDefinition beanDefinition){
        //1 执行BeanPostProcessor Before处理  (14)
        Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
     

        //待完成内容:invokeInitMethods(beanName, wrappedBean, beanDefinition);
        invokeInitMethods(beanName, wrappedBean, beanDefinition);

        //2 执行BeanPostProcessor After处理
        wrappedBean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
        return wrappedBean;
    }

(14)AbstractAutowireCapableBeanFactory
执行BeanPostProcessor Before处理

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()){
            //(15)
            Object current = processor.postProcessBeforeInitialization(result, beanName);
            if (null == current){
                return result;
            }
            result = current;
        }
        return result;
    }

(15)MyBeanPostProcessor
具体的执行BeanPostProcessor Before处理方法

 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

        if ("userService".equals(beanName)){
            UserService userService = (UserService) bean;
            userService.setLocation("改为:北京");
        }
        return bean;
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一定会去到彩虹海的麦当

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

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

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

打赏作者

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

抵扣说明:

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

余额充值