Spring最重要的部分之一就是提供了IoC容器,爲何須要IoC容器呢?IoC是依賴倒置,或者說是控制反轉的意思,控制反轉這個詞也許咱們耳朵已經聽出繭子了,也正是由於如此,也阻礙了咱們從新思考這個詞。java
如今,咱們從新思考一下什麼是"控制反轉"?咱們不下定義,咱們就結合業務場景來思考,例如,咱們的web應用,在Controller層會依賴Service層的邏輯,不一樣的Controller可能會依賴相同的service層對象。例如,庫存和積分的Controller都會依賴用戶的Service。web
若是沒有Spring,咱們常見的作法是在每個Controller中都建立用戶的Service,這些建立邏輯可能比較複雜。spring
這樣帶來的問題就是,建立對象的邏輯分散的處處都是,每一地方都會建立新的對象。springboot
Spring怎麼解決這個問題的呢?使用IoC容器。依賴倒置提如今什麼地方?原來是Controller依賴Service,如今不依賴了麼?不是,不過控制權轉移了,都是有Spring來管理,Spring建立對象,而後注入到須要的對象之中。mvc
這樣的好處是顯而易見的,建立邏輯都不用咱們管了,依賴對象也不用咱們關心了,不少對象能夠共享,不用重複建立、銷燬。app
BeanDefinition解析有2個重要的接口,它們分別是BeanDefinitionReader和BeanDefinitionParser。ide
BeanDefinitionReader的做用是讀取bean的信息,例如,BeanDefinitionReader的間接實現類XmlBeanDefinitionReader就是從xml文件中讀取bean的信息。ui
讀取到bean信息了,還須要把這些信息解析爲BeanDefinition,這個過程是BeanDefinitionParser的職責,例如,AnnotationDrivenBeanDefinitionParser就是從註解中解析BeanDefinition。this
在實際的解析中可能具體的解析類是其餘的,例如XmlBeanDefinitionReader,實際註冊是利用BeanDefinitionDocumentReader接口的實現類DefaultBeanDefinitionDocumentReader。spa
DefaultBeanDefinitionDocumentReader實際上只處理了一些標籤,例如beans、alias、name、import、resource、profile等。
像常見的標籤bean、ref等標籤實際是BeanDefinitionParserDelegate處理的,BeanDefinitionParserDelegate也不會處理所有標籤。
BeanDefinitionParserDelegate會經過NamespaceHandler來處理一些自定義標籤,像下面的標籤都是經過對應的NamespaceHandler實現類來處理的。
<tx:annotation-driven/> <tx:advice id="txAdvice" transaction-manager="myTracnsactionManager"> <aop:config> <dubbo:reference id="xxxService" interface="xxx.XxxService"/> <context:annotation-config /> <mvc:interceptors>
NamespaceHandler會經過NamespaceHandlerSupport來找到一個合適的BeanDefinitionParser,而後經過BeanDefinitionParser的parse方法來解析出對應的BeanDefinition。
有了BeanDefinition,怎樣經過BeanDefinition建立真正的bean的呢?
BeanFactoryPostProcessor
BeanPostProcessor
BeanFactoryAware
BeanNameAware
InitializingBean
DisposableBean
InstantiationAwareBeanPostProcessorAdapter
InstantiationAwareBeanPostProcessor
按照類型匹配,默認必須找到,找不到就拋異常,若是不是必須,能夠設置require=false。這個和經過xml配置autowire屬性(也就是@Bean的autowire屬性。)差很少。
不過xml方式autowire必須有setter方法,而@Autowired能夠不用setter方法,而且@Autowired只有經過type注入,要經過name方式還得多加一個@Qualifier("name")註解。
@Autowired的註解處理器是AutowiredAnnotationBeanPostProcessor。
在AbstractAutowireCapableBeanFactory中有一個ignoreDependencyInterface方法,能夠設置不容許setter注入,這個主要是爲了不一些特殊的類被隨意注入了,例如ApplicationContext、BeanFactory等。這樣要獲取ApplicationContext必須實現ApplicationContextAware,而不只僅是在類中添加一個ApplicationContext屬性就能夠了。
最先的數據類型轉換是使用的PropertyEditor,支持的是String和Object之間的轉換,在Spring中主要用在2個地方。
通常不會直接實現PropertyEditor接口,而是直接繼承PropertyEditorSupport類。
PropertyEditor是經過org.springframework.beans.factory.config.CustomEditorConfigurer註冊的。也能夠實現PropertyEditorRegistrar,而後將PropertyEditorRegistrar設置到CustomEditorConfigurer中。
注意PropertyEditorRegistry和PropertyEditorRegistrar,Registry是登記處,Registrar是以ar結尾,表示登記員的意思。因此顧名思義PropertyEditorRegistry是註冊PropertyEditor的地方,PropertyEditorRegistrar的做用是把PropertyEditor註冊到本身管理的PropertyEditorRegistry中。
Spring 3開始增長了一個Converter接口,能夠完成任意2個類型之間的轉換,這點比PropertyEditor強,PropertyEditor只能是String與Object之間的轉換。
Converter的通常玩法是,實現ConverterFactory接口,在實現類中給一個靜態內部類實現Converter。ConverterFactory的getConverter返回這個Converter就能夠了。
若是是更加複雜的轉換能夠考慮GenericConverter和ConditionalConverter接口。
ConversionService接口爲類型轉換提供統一轉換API來執行運行時的轉換邏輯,使用的是外觀模式(facade)。配置ConversionService只須要配置一個id爲conversionService的org.springframework.context.support.ConversionServiceFactoryBean就能夠了。自定義的Converter也能夠經過ConversionServiceFactoryBean設置。
org.springframework.format.Formatter接口和PropertyEditor接口差很少,不過結構更加清晰,PropertyEditor接口有不少GUI相關的方法,而Spring的Formatter接口,就是繼承了從類型T到String的Printer接口和從String到類型T的Parser接口。
註解驅動的Formatter能夠實現AnnotationFormatterFactory提供支持,Formatter也有registry和registrar,它們分別是FormatterRegistry和FormatterRegistrar。
Spring MVC的AnnotationDrivenBeanDefinitionParser中若是,若是包含「conversion-service」就會註冊一個FormattingConversionServiceFactoryBean,FormattingConversionServiceFactoryBean持有一個FormattingConversionService。
mvc中的數據轉換是HttpInputMessage、HttpOutputMessage和Java數據類型之間的轉換,實現HttpMessageConverter接口就能夠了。
咱們知道MVC中有2個重要的接口一個是HandlerAdapter,另外一個是HandlerMapping。簡化點說HandlerMapping作的事情就是把請求URL找到對應的method來處理。HandlerAdapter看名字有點像適配器模式,實際上更像是代理模式。
HandlerAdapter的做用就是處理一些公共的邏輯,例如解析@RequestParam、@PathVariable、@RequestBody、@ResponseBody等註解...
想想HTTP協議或者直接經過Servlet處理須要處理的邏輯,再對比一下咱們使用@Controller和@RequestMapping註解以後的方法的邏輯,就知道HandlerAdapter作了多少事情了。正是由於如此、HandlerAdapter的能夠定製的程度也高。
如今spring mvc中默認使用的HandlerAdapter和HandlerMapping是: RequestMappingHandlerAdapter RequestMappingHandlerMapping 這2個類是在DispatcherServlet.properties配置的。
使用http://www.javashuo.com/tag/mvc:annotation-driven標籤,默認註冊的也是這2個類,前面已經介紹了這種標籤的解析,感興趣能夠本身查看一下MvcNamespaceHandler和AnnotationDrivenBeanDefinitionParser這2個類,NamespaceHandler是在META-INF的spring.handler中配置的,自定義NamespaceHandler的時候注意建立對應的xsd和spring.handler文件。
spring mvc中處理參數和返回值的主要接口和類:
HandlerMethodReturnValueHandlerComposite HandlerMethodReturnValueHandler HandlerMethodArgumentResolverComposite HandlerMethodArgumentResolver
典型的組合模式,不過Composite中採用的不是遍歷,而是找到第一個支持的Handler來處理。 看RequestMappingHandlerAdapter源碼中有下面2個方法,用來初始化默認的HandlerMethodReturnValueHandler和HandlerMethodArgumentResolver。
RequestMappingHandlerAdapter#getDefaultArgumentResolvers RequestMappingHandlerAdapter#getDefaultReturnValueHandlers
還有一個HttpMessageConverter集合,是用來給RequestResponseBodyMethodProcessor、RequestPartMethodArgumentResolver、HttpEntityMethodProcessor、ResponseBodyEmitterReturnValueHandler這幾個參數返回值處理器使用的。@ResponseBody和@RequestBody很是常見,通常咱們知道出問題是在什麼地方,可是當參數和返回值是HttpEntity的時候,也會使用到HttpMessageConverter,這個須要注意,例如,使用HttpEntity做爲返回值傳輸文件,就得看一下有沒有配置ByteArrayHttpMessageConverter這個轉換器。
BeanFactory,以Factory結尾,表示它是一個工廠類(接口),用於管理Bean的一個工廠。在Spring中,BeanFactory是IOC容器的核心接口,它的職責包括:實例化、定位、配置應用程序中的對象及創建這些對象間的依賴。
FactoryBean,以Bean結尾,表示它是一個Bean,不一樣於普通Bean的是它實現了FactoryBean<T>接口的Bean,根據該Bean的ID從BeanFactory中獲取的其實是FactoryBean的getObject()返回的對象,而不是FactoryBean自己,若是要獲取FactoryBean對象,請在id前面加一個&符號來獲取。
Environment主要是讀取系統變量和屬性,固然也會出來classpath或者指定路徑下的properties文件,主要涉及的類有:
@PropertySource({"classpath:base.properties"}) @Component public class BaseBean { @Value("${host:127.0.0.1}") private String host; @Value("${base.host:127.0.0.1}") private String baseHost; @Value("#{'Hello World'.concat('!')}") private String helloWorld; @Value("#{'${base.server.name}'.split(',')}") private List<String> servers; public String getHost() { return host; } public void setHost(String host) { this.host = host; } public String getBaseHost() { return baseHost; } public void setBaseHost(String baseHost) { this.baseHost = baseHost; } public String getHelloWorld() { return helloWorld; } public void setHelloWorld(String helloWorld) { this.helloWorld = helloWorld; } public List<String> getServers() { return servers; } public void setServers(List<String> servers) { this.servers = servers; } @Override public String toString() { return "BaseBean{" + "host='" + host + '\'' + ", baseHost='" + baseHost + '\'' + ", helloWorld='" + helloWorld + '\'' + ", servers=" + servers + '}'; } }
@ConfigurationProperties是springboot的中的,不能和@Value同時使用,只須要使用一個就能夠了。