Spring加载过程及核心类

5,710 阅读2分钟

1. ClassPathXmlApplicationContext

在非web环境中,常用ClassPathXmlApplicationContext来创建ApplicationContext

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

1.1 继承关系

下面以ClassPathXmlApplicationContext来看加载流程。

2. 加载步骤

    1. ClassPathXmlApplicationContext设置配置文件位置。
    1. AbstractApplicationContext.refresh(): 设置spring上下文环境,创建BeanFacotry并设置。
    1. AbstractRefreshableApplicationContext.refreshBeanFactory.
    1. AbstractRefreshableApplicationContext. loadBeanDefinitions, 抽象方法,由子类实现。
    1. AbstractXmlApplicationContext.loadBeanDefinitions: 读取xml配置信息,并创建BeanDefinition注册到Spring环境。
    1. AbstractAutowireCapableBeanFactory.createBean: 由之前创建的BeanFactory创建bean对象,并设置各种属性和调用接口。

3. 核心类

  • BeanDefinition: Bean的定义类, 和xml里的配置一一对应;
  • BeanFacotry: Bean工厂接口;
  • BeanDefinitionRegistry: BeanDefinition的注册定义接口;
  • DefaultListableBeanFactory: ListableBeanFactory(extends BeanFactory)和BeanDefinition的默认实现,提供BeanDefinition注册功能;
  • ApplicationContext: Spring上下文环境;
  • AbstractApplicationContext: 执行refresh()方法;
  • AbstractRefreshableApplicationContext: 提供抽象方法loadBeanDefinitions(DefaultListableBeanFactory beanFactory) 用于加载BeanDefinition.

3.1 BeanDefinition

  • 1.RootBeanDefinition: 普通bean。
  • 2.ChildBeanDefinition: 子bean,spring内部使用,一般推荐使用GenericBeanDefinition代替;
  • 3.可以调用BeanDefinitionReaderUtils.createBeanDefinition创建,会返回AbstractBeanDefinition。
3.1.1 手动创建bean的定义
 public static void main(String[] args) throws ClassNotFoundException {

        //1 声明BeanDefinition
        BeanDefinition userDaoDefinition = new RootBeanDefinition(UserDao.class);

        BeanDefinition beanDefinition = BeanDefinitionReaderUtils.createBeanDefinition(null, User33Service.class.getName(), null);
        
        //2 创建BeanFactory,并注册beanDefinitions
        beanDefinition.getPropertyValues().addPropertyValue("userDao", new RuntimeBeanReference("userDao"));
        List<Integer> values = new ManagedList<>();
        values.add(1);
        values.add(2);
        values.add(3);
        beanDefinition.getPropertyValues().addPropertyValue("values", values);

        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerBeanDefinition("userService", beanDefinition);
        beanFactory.registerBeanDefinition("userDao", userDaoDefinition);

        User33Service user33Service = (User33Service) beanFactory.getBean("userService");
        System.out.println(user33Service.getUser());
    }
  • 1.创建BeanDefinition对象,BeanDefinition的字段,和xml中的配置节点一致;
  • 2.创建DefaultListableBeanFactory对象,或实现接口BeanFactoryPostProcessor以获取到当前的beanFactory;
  • 3.调用DefaultListableBeanFactory的registerBeanDefinition。

BeanDefinition中通过 beanDefinition.getPropertyValues().addPropertyValue 设置bean的属性。

3.1.2 xml标签与BeanDefinition属性类型映射:
  • 属性:
  • ref : RuntimeBeanReference
  • value : TypedStringValue
  • property的子标签:
  • bean: BeanDefinitionHolder
  • ref : RuntimeBeanReference
  • idref : RuntimeBeanNameReference
  • value : TypedStringValue
  • null : TypedStringValue
  • array : ManagedArray or List 代码中已经被强制转换为List
  • list : ManagedList or List 代码中已经被强制转换为List
  • set : ManagedSet or Set 代码中已经被强制转换为Set
  • map : ManagedMap or Map 代码中已经被强制转换为Map
  • props : ManagedProperties

3.2 ApplicationContext

Spring中的ApplicationContext基本都是继承自AbstractRefreshableConfigApplicationContext,比如ClassPathXmlApplicationContext,FileSystemXmlApplicationContext等。

自定义ApplicationContext:

public class MyContext extends AbstractRefreshableConfigApplicationContext {

    public MyContext(){
        super.addApplicationListener(new MyListener());
        super.refresh();
    }

    @Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {

        RootBeanDefinition beanDefinition = new RootBeanDefinition(CustomService.class);

        beanFactory.registerBeanDefinition("testBean", beanDefinition);

        beanFactory.registerBeanDefinition("childBean", new GenericBeanDefinition(beanDefinition));

        GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
        genericBeanDefinition.setBeanClass(CustomService.class);
        beanFactory.registerBeanDefinition("genericBean", genericBeanDefinition);
    }
}
  • 1 继承AbstractRefreshableConfigApplicationContext;
  • 2 实现loadBeanDefinitions,注册bean。

3.3 实现自己的spring环境

  • 1.继承AbstractRefreshableConfigApplicationContext,并在构造函数中调用super.refresh();

  • 2.实现loadBeanDefinitions;

  • 3.创建BeanDefinition(AbstractBeanDefinition, RootBeanDefinition, 或 GenericBeanDefinition);

  • 4.通过beanDefinition.getPropertyValues().addPropertyValue设置bean的属性;

  • 5.beanFactory.registerBeanDefinition注册bean。