1. 程式人生 > 程式設計 >Spring載入過程及核心類

Spring載入過程及核心類

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。