Spring註解注入原理
Spring容器框架包org.springframework.stereotype下Controller註解介面原始碼如下:
@Target({java.lang.annotation.ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller
{
public abstract String value();
}
@Target({java.lang.annotation.ElementType.Type})表是註解使用在類上;
@Retention(RetentionPolicy.RUNTIME)表示註解在程式執行狀態下還有效;
@Component表示該類物件以預設單例模式存放在spring容器框架中;
@Documented無關重要,略;
這個註解在程式執行狀態下還有效。再看其他的註解@Respository,@Ser vice等,這兩個註解的原始碼和Controller的原始碼一樣,除了介面名,都共有一個value抽象函式。
這些所有的註解都會被component註解介面註解,所有“繼承”了component註解介面的註解修飾使用者的類會被spring中的註解處理器獲取(getAnonations()),判定存在component註解後,註解處理器會在spring容器框架中根據使用者類的全限定名通過java的反射機制建立這個使用者類的物件,並放到spring容器框架中進行管理。
以上這些描述是我基於對註解系統的理解而描述的。
bean建立的幾個重要步驟:
1) 建立bean例項,也就是bean的實體化,建立過程不僅僅只有java的反射機制,還結合了動態代理的方式
2) 記錄建立bean的objectFactory
3) 屬性注入
4) 初始化bean
5) 註冊disposablebean
Spring bean的生命週期:
說完bean的建立過程,那spring是如何找到這些bean的類檔案的呢?
我們在spring的配置檔案中,有這樣一個標籤節點<context:component-scan>,在這個標籤的屬性base-package中設定要掃描的包。那麼可以推斷,spring框架中肯定有根據base-package屬性掃描得到所有需要管理的bean物件,這個節點中的所有屬性會被放入掃描模組物件工具中去,結果就是將所有的bean物件放到spring的容器中去。
注意:spring容器框架額註解都會在running狀態下的,所以執行時載入的檔案都是已經編譯後的class檔案.所以使用的是asm技術讀取class檔案的位元組碼轉化成MetadataReader中的AnnotationMetadataReadingVisitor結構.
標籤<context:component-scan>的解析總結如下:
1)根據配置利用asm技術掃描.class檔案,並將包含@Component及元註解為@Component的註解@Controller、@Service、@Repository或者還支援Java EE 6的@link javax.annotation.ManagedBean和jsr - 330的 @link javax.inject.Named,如果可用。的bean註冊到beanFactory中
2)註冊註解後置處理器,主要是處理屬性或方法中的註解,包含:
註冊@Configuration處理器ConfigurationClassPostProcessor,
註冊@Autowired、@Value、@Inject處理器AutowiredAnnotationBeanPostProcessor,
註冊@Required處理器RequiredAnnotationBeanPostProcessor、在支援JSR-250條件下注冊javax.annotation包下註解處理器CommonAnnotationBeanPostProcessor,包括@PostConstruct、@PreDestroy、@Resource註解等、支援jpa的條件下,註冊org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor處理器,處理jpa相關注解註冊@EventListener處理器EventListenerMethodProcessor
註解處理器的的例項化和處理器的註冊時同步的,例項化後放入到beanFactory的beanProcessors列表中去。
Spring框架的核心就是IOC,通過controller一類註解的bean的例項化過程可以大體總結spring註解的工作原理:
1)利用asm技術掃描class檔案,轉化成Springbean結構,把符合掃描規則的(主要是是否有相關的註解標註,例如@Component)bean註冊到Spring 容器中beanFactory
2)註冊處理器,包括註解處理器
4)例項化處理器(包括註解處理器),並將其註冊到容器的beanPostProcessors列表中
5)建立bean的過程中,屬性注入或者初始化bean時會呼叫對應的註解處理器進行處理。
舉例註解@Autowired
。對於這個註解,您需要在xml中配置這個註解的處理器
AutowiredAnnotationBeanPostProcessor,這個處理器會掃描容器中所有的bean物件,發現bean中擁有@Autowired註解的時候會自動去找到容器中和這個註解修飾型別匹配的bean物件,並注入到對應的地方去。
那為什麼AutowiredAnnotationBeanPostProcessor這個處理器物件我怎麼在配置檔案中沒有看到設定呢?那是因為在spring解析<context:component>標籤的時候預設這個註解被隱示配置了,還有其他的註解處理器,如CommonAnnoationBeanPostProcessor。