1. 程式人生 > >spring 為什麽可以一統江湖

spring 為什麽可以一統江湖

can 註冊 con 後置處理器 println select fish inf nmon

spring 為什麽可以一統江湖

Inversion of Contro 簡稱IOC 是面向對象編程中的一種設計原則,可以用來減低計算機代碼之間的耦合度。也就是面向接口編程的思想。
簡單的說就是使用配置的方式,修改程序代碼的實現。能靈活的切換代碼,不用修改邏輯代碼。其實就是解決硬編碼創建對象的問題。

學習的路線設定

  • 了解有多少種方式添加對象到容器中

    這個很重要,在工作中經常出現類找不到的異常,熟悉這個的話,問題很容易找到。

  • 再從spring對一個類的處理的源碼開始解析spring的原理

Spring配置有兩種,詳細法就可以參考一下Spring的使用教程。

xml配置與註解方式配置。其他本質是一樣的。

  • xml
  • 配置類上加Configuration

掃描加載bean的規則有,這些不是很重要.

  • @bean
    <bean id="person" class="com.enjoy.cap1.Person">
        <property name="name" value="wolf"></property>
        <property name="age" value="19"></property>
    </bean>
或在Configuration類中使用
@Bean("person")
  • @@Component與@ComponentScan(value = "bgy.bean")

    一般用這種,在類上加@Component就可以ComponentScan加載到容器中

    @Component
     public class Dog{}
  • @@Import(bgy.beanout.Fly.class) 單獨加入
@Configuration
@Import(value = { Dog.class })
public class Cap6MainConfig {}
  • 實現ImportSelector
public class MyImportSelector implements ImportSelector{
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata){
        //返回全類名的bean
        return new String[]{"com.enjoy.cap6.bean.Fish","com.enjoy.cap6.bean.Tiger"};
    }
}

//把MyImportSelector當成bean導入
@Import(value = {ImportSelector.class})
  • 使用FactoryBean
public class JamesFactoryBean implements FactoryBean<Monkey>{

    @Override
    public Monkey getObject() throws Exception {
        // TODO Auto-generated method stub
        return new Monkey();
    }

    @Override
    public Class<?> getObjectType() {
        // TODO Auto-generated method stub
        return Monkey.class;
    }
    
    @Override
    public boolean isSingleton() {
        return true;
    }
}
  • 使用JamesImportBeanDefinitionRegistrar
public class JamesImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    /*
    *AnnotationMetadata:當前類的註解信息
    *BeanDefinitionRegistry:BeanDefinition註冊類
    *    把所有需要添加到容器中的bean加入;
    *    @Scope
    */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean bean1 = registry.containsBeanDefinition("com.enjoy.cap6.bean.Dog");
        boolean bean2 = registry.containsBeanDefinition("com.enjoy.cap6.bean.Cat");
        //如果Dog和Cat同時存在於我們IOC容器中,那麽創建Pig類, 加入到容器
        //對於我們要註冊的bean, 給bean進行封裝,
        if(bean1 && bean2){
            RootBeanDefinition beanDefinition = new RootBeanDefinition(Pig.class);
            registry.registerBeanDefinition("pig", beanDefinition);
        }
    }

}

小結:
實現的spring包為:spring-context。上下文容器類都是繼承了AbstractApplicationContext 類的。重點:開發時可以按需要自定義上下文。
技術分享圖片

spring 源碼解析

從加載容器開始

      ApplicationContext applicationContext=new AnnotationConfigApplicationContext(myconfig.class);
       // ApplicationContext applicationContext=new ClassPathXmlApplicationContext("beans.xml");

上下文抽象類,此設計用的是模板方法設計模式, 在refresh裏 固定好加載時的方法調用順序。

 public void refresh() throws BeansException, IllegalStateException {
        Object var1 = this.startupShutdownMonitor;
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();//加載 bean的配置定義
            this.prepareBeanFactory(beanFactory);

            try {
                this.postProcessBeanFactory(beanFactory);
                this.invokeBeanFactoryPostProcessors(beanFactory);//如果有配置類則添加配置類處理器,並將優先級排為最高
                this.registerBeanPostProcessors(beanFactory);//註冊其他的處理器,並設置好處理順序。
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                this.finishBeanFactoryInitialization(beanFactory);//註冊所有註入進來的bean實例到容器中
                this.finishRefresh();
            } catch (BeansException var9) {
                if(this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }

                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }

        }
    }

BeanPostProcessors

後置處理器接口,實現了這個接口類可以對所有的類初始化方法進行攔截處理,分別為:postProcessBeforeInitialization,postProcessAfterInitialization

@Component
public class MyBeanPostProcessor implements BeanPostProcessor{
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        //返回一個的對象(傳過來的對象)
        //在初始化方法調用之前進行後置處理工作,
        //什麽時候調用它: init-method=init之前調用
        System.out.println("postProcessBeforeInitialization...."+beanName+"..."+bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization...."+beanName+"..."+bean);
        return bean;
    }
}

spring 應用組件擴展

待發布

spring 為什麽可以一統江湖