自定義的Bean定義html
class MyBeanDefinition{
public String id;
public String className;
public String value;
public MyBeanDefinition(String id, String className, String value) {
this.id = id;
this.className = className;
this.value = value;
}
}
複製代碼
自定義的Bean工廠node
class MyBeanFactory {
Map<String, Object> beanMap = new HashMap<>();
public MyBeanFactory(MyBeanDefinition beanDefinition) throws ClassNotFoundException,
IllegalAccessException, InstantiationException {
Class<?> beanClass = Class.forName(beanDefinition.className);
Object bean = beanClass.newInstance();
((UserService) bean).setName(beanDefinition.value);
beanMap.put(beanDefinition.id, bean);
}
public Object getBean(String id) {
return beanMap.get(id);
}
}
複製代碼
測試傻瓜版IOC容器spring
public class EasyIOC {
public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
MyBeanDefinition beanDefinition = new MyBeanDefinition("userService",
"com.valarchie.UserService", "archie");
MyBeanFactory beanFactory = new MyBeanFactory(beanDefinition);
UserService userService = (UserService) beanFactory.getBean("userService");
System.out.println(userService.getName());
}
}
複製代碼
按照個人理解,我總結爲如下三步設計模式
因此,接下來咱們不會通盤分析整個IOC的流程,由於旁枝細節太多讀者看完也雲裏霧裏抓不到重點。
咱們經過分析最重要的這條代碼主幹線來理解IOC的過程。數組
首先咱們從xml的配置方式開始分析,由於Spring最初的配置方式就是利用xml來進行配置,因此大部分人對xml的配置形式較爲熟悉,也比較方便理解。緩存
從ClassPathXmlApplicationContext的構造器開始講起。bash
public class TestSpring {
public static void main(String[] args) {
// IOC容器的啓動就從ClassPathXmlApplicationContext的構造方法開始
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");
UserService userService = (UserService) context.getBean("userService");
System.out.println(userService.getName());
}
}
複製代碼
進入到構造方法中,調用重載的另外一個構造方法。app
// 建立ClassPathXmlApplicationContext,加載給定的位置的xml文件,並自動刷新context
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
複製代碼
重載的構造方法中,因爲剛纔parrent參數傳爲null,因此不設置父容器。refresh剛纔設置爲true,流程就會進入refresh()方法中dom
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
// 因爲以前的方法調用將parent設置爲null,因此咱們就不分析了
super(parent);
// 設置路徑數組,並依次對配置路徑進行簡單佔位符替換處理,比較簡單,咱們也不進入分析了
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
複製代碼
整個refresh()方法中就是IOC容器啓動的主幹脈絡了,Spring採用了模板方法設計模式進行refresh()方法的設計,先規定好整個IOC容器的具體步驟,而後將每個小步驟由各類不一樣的子類本身實現。ide
全部重要的操做都是圍繞着BeanFactory在進行。
在註釋當中,咱們詳細的列出了每一步方法所完成的事情。ApplicationContext內部持有了FactoryBean的實例。其實ApplicationContext自己最上層的父接口也是BeanFactory,他拓展了BeanFactory以外的功能(提供國際化的消息訪問、資源訪問,如URL和文件、事件傳播、載入多個(有繼承關係)上下文)
咱們先經過閱讀代碼中的註釋來了解大概的脈絡。
public void refresh() throws BeansException, IllegalStateException {
// 先加鎖防止啓動、結束衝突
synchronized (this.startupShutdownMonitor) {
// 在刷新以前作一些準備工做
// 設置啓動的時間、相關狀態的標誌位(活動、關閉)、初始化佔位符屬性源,並確認
// 每一個標記爲必須的屬性都是可解析的。
prepareRefresh();
// 獲取一個已刷新的BeanFactory實例。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 定義好Bean工廠的環境特性,例如類加載器,或者後置處理器
prepareBeanFactory(beanFactory);
try {
// 設置在BeanFactory完成初始化以後作一些後置操做,spring留給子類的擴展。
postProcessBeanFactory(beanFactory);
// 啓動以前已設置的BeanFactory後置處理器
invokeBeanFactoryPostProcessors(beanFactory);
// 註冊Bean處理器
registerBeanPostProcessors(beanFactory);
// 爲咱們的應用上下文設置消息源(i18n)
initMessageSource();
// 初始化事件廣播器
initApplicationEventMulticaster();
// 初始化特殊的Bean在特殊的Context中,默認實現爲空,交給各個具體子類實現
onRefresh();
// 檢查監聽器並註冊
registerListeners();
// 實例化全部非懶加載的Bean
finishBeanFactoryInitialization(beanFactory);
// 最後一步發佈相應的事件
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 若是啓動失敗的話,要銷燬以前建立的Beans。
destroyBeans();
// 重置ApplicationContext內部active的標誌位
cancelRefresh(ex);
// 向調用者拋出異常
throw ex;
}
finally {
// 重置Spring核心內的緩存,由於咱們可能再也不須要單例bean相關的元數據
resetCommonCaches();
}
}
}
複製代碼
閱讀完以後咱們重點關注obtainFreshBeanFactory()、finishBeanFactoryInitialization(beanFactory)這兩個方法,由於實質上整個IOC的流程都在這兩個方法當中,其餘的方法一部分是Spring預留給用戶的自定義操做如BeanFactory的後置處理器和Bean後置處理器,一部分是關鍵啓動事件的發佈和監聽操做,一部分是關於AOP的操做。
首先,先從obtainFreshBeanFactory()開始提及。
在getBeanFactory()方法以前,先調用refreshBeanFactory()方法進行刷新。咱們先說明一下,getBeanFactory()很是簡單,默認實現只是將上一步刷新成功好構建好的Bean工廠進行返回。返回出去的Bean工廠已經加載好Bean定義了。因此在refreshBeanFactory()這個方法中已經包含了第一步讀取xml文件構建DOM對象和第二步解析DOM中的元素生成Bean定義進行保存。記住,這裏僅僅是保存好Bean定義,此時並未涉及Bean的實例化。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
複製代碼
進入refreshBeanFactory()方法中
protected final void refreshBeanFactory() throws BeansException {
// 若是當前ApplicationContext中已存在FactoryBean的話進行銷燬
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 先生成一個BeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 設置序列化
beanFactory.setSerializationId(getId());
// 設置是否能夠覆蓋Bean定義和是否能夠循環依賴,具體我就不解釋了
customizeBeanFactory(beanFactory);
// 加載Bean定義到Factory當中去
// 重點!
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
複製代碼
接下來,進入核心方法loadBeanDefinitions(beanFactory)中,參數是剛建立的beanFactory
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 根據傳入的beanfactory建立一個xml讀取器
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// 設置bean定義讀取器的相關資源加載環境
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// 這個方法讓子類自定義讀取器Reader的初始化
initBeanDefinitionReader(beanDefinitionReader);
// 接着開始實際加載Bean定義
loadBeanDefinitions(beanDefinitionReader);
}
複製代碼
進入loadBeanDefinitions(beanDefinitionReader)方法中,參數是剛剛建立好的Reader讀取器。
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
// 若是有已經生成好的Resouce實例的話就直接進行解析。
// 默認的實現是返回null,由子類自行實現。
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
// 沒有Resouces的話就進行路徑解析。
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
複製代碼
咱們進入reader.loadBeanDefinitions(configLocations)方法中,這裏面方法調用有點繞,我這邊只簡單地描述一下
該方法會根據多個不一樣位置的xml文件依次進行處理。 接着會對路徑的不一樣寫法進行不一樣處理,例如classpath或者WEB-INF的前綴路徑。 根據傳入的locations變量生成對應的Resouces。 緊接着進入reader.loadBeanDefinitions(resource)此時參數是Resource。 在通過一層進入loadBeanDefinitions(new EncodedResource(resource))的方法調用中。
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
// 經過ThreadLocal實現的當前currentResource
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
// 最主要的方法在這段
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
// 傳入流對象,並設置好編碼
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
複製代碼
該方法最主要是建立了對應的輸入流,並設置好編碼。
而後開始調用doLoadBeanDefinitions()方法。
// 內部核心代碼就這兩句
Document doc = doLoadDocument(inputSource, resource);
return registerBeanDefinitions(doc, resource);
複製代碼
在loadDocument()方法中會生成一個DocumentBuilderImpl對象,這個對象會調用parse方法,在parse方法中使用SAX進行解析剛纔的輸入流包裝的InputSource,生成DOM對象返回。
public Document parse(InputSource is) throws SAXException, IOException {
if (is == null) {
throw new IllegalArgumentException(
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
"jaxp-null-input-source", null));
}
if (fSchemaValidator != null) {
if (fSchemaValidationManager != null) {
fSchemaValidationManager.reset();
fUnparsedEntityHandler.reset();
}
resetSchemaValidator();
}
// 解析xml
domParser.parse(is);
// 獲取剛纔解析好的dom
Document doc = domParser.getDocument();
domParser.dropDocumentReferences();
return doc;
}
複製代碼
// 內部核心代碼就這兩句
Document doc = doLoadDocument(inputSource, resource);
return registerBeanDefinitions(doc, resource);
複製代碼
咱們再回到剛剛講到的這兩句核心代碼,第一句獲取DOM對象後,緊接着第二句registerBeanDefinitions(doc, resource)開始了bean定義的註冊工做。
進入registerBeanDefinitions(doc, resource)方法中
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// 生成DOM讀取器,這個和剛纔的讀取器不同,以前的讀取器是xml讀取器。
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
// 獲取以前的bean定義數量
int countBefore = getRegistry().getBeanDefinitionCount();
// 進入重點
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
// 用剛剛又建立的bean定義數量 - 以前的bean定義數量 = 剛剛一共建立的bean定義
return getRegistry().getBeanDefinitionCount() - countBefore;
}
複製代碼
進入documentReader.registerBeanDefinitions(doc, createReaderContext(resource))方法。 方法內讀取文檔的root元素。
protected void doRegisterBeanDefinitions(Element root) {
// Any nested <beans> elements will cause recursion in this method. In
// order to propagate and preserve <beans> default-* attributes correctly,
// keep track of the current (parent) delegate, which may be null. Create
// the new (child) delegate with a reference to the parent for fallback purposes,
// then ultimately reset this.delegate back to its original (parent) reference.
// this behavior emulates a stack of delegates without actually necessitating one.
BeanDefinitionParserDelegate parent = this.delegate;
// 生成Bean定義解析類
this.delegate = createDelegate(getReaderContext(), root, parent);
// 若是是xml文檔中的namespace,進行相應處理
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
// spring預留給子類的拓展性方法
preProcessXml(root);
// 重點
// 開始解析Bean定義
parseBeanDefinitions(root, this.delegate);
// spring預留給子類的拓展性方法
postProcessXml(root);
this.delegate = parent;
}
複製代碼
進入parseBeanDefinitions(root, this.delegate)。將以前的文檔對象和bean定義解析類做爲參數傳入。
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
// 遍歷去解析根節點的每一個子節點元素
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
// 若是是標籤元素的話
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
// 解析默認的元素
// 重點
parseDefaultElement(ele, delegate);
}
else {
// 解析指定自定義元素
delegate.parseCustomElement(ele);
}
}
}
}
else {
// 非默認命名空間的,進行自定義解析,命名空間就是xml文檔頭內的xmlns,用來定義標籤。
delegate.parseCustomElement(root);
}
}
複製代碼
進入到parseDefaultElement(ele, delegate)當中,會發現其實對四種標籤進行分別的解析。
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
// 分析Bean標籤
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
複製代碼
咱們主要分析Bean元素標籤的解析,進入processBeanDefinition(ele, delegate)方法中最內層。
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
// 獲取bean標籤內的id
String id = ele.getAttribute(ID_ATTRIBUTE);
// 獲取bean標籤內的name
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
// 設置多別名
List<String> aliases = new ArrayList<String>();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
// 當沒有設置id的時候
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
// 檢查beanName是否惟一
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
// 內部作了Bean標籤的解析工做
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
beanName = this.readerContext.generateBeanName(beanDefinition);
// Register an alias for the plain bean class name, if still possible,
// if the generator returned the class name plus a suffix.
// This is expected for Spring 1.2/2.0 backwards compatibility.
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
複製代碼
將解析好的Bean定義並附加別名數組填入new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray)中進行返回。而後調用如下這個方法。
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())
複製代碼
最主要的操做就是將剛纔解析好的Bean定義放入beanDefinitionMap中去。
咱們回到最開始的refresh方法中,在finishBeanFactoryInitialization(beanFactory)方法中,開始實例化非懶加載的Bean對象。咱們跟着調用鏈進入到preInstantiateSingletons()方法中
@Override
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}
// 將以前作好的bean定義名列表拷貝放進beanNames中,而後開始遍歷
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
// 觸發全部非懶加載的單例Bean實例化
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 若是非抽象而且是單例和非懶加載的話
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 檢測是不是工廠方法Bean。 建立Bean的不一樣方式,讀者可自行百度。
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else {
getBean(beanName);
}
}
}
// 關於實例化以後作的自定義操做代碼省略....
}
複製代碼
在該方法中根據Bean實例是經過工廠方法實例仍是普通實例化,最主要的方法仍是getBean(beanName)方法。咱們繼續分析普通實例化的過程。進入getBean()方法當中doGetBean()方法,發現方法參數doGetBean(name, null, null, false)後三個參數所有爲null,它就是整個IOC中的核心代碼。
代碼中先經過實例化Bean,實例化好以後再判斷該Bean所需的依賴,並遞歸調用進行實例化bean,成功後整個IOC的核心流程也就完成了。
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 若是當前Bean正在建立中的話就直接失敗,
// 能夠陷入了循環引用。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 檢測Bean定義是否出如今父Bean工廠
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 父工廠不爲null而且當前不包含這個Bean定義時
// 從父工廠去返回Bean
String nameToLookup = originalBeanName(name);
if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
// 若是不須要類型檢查的話 標記爲已建立
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 將子Bean定義與父Bean定義進行整合
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 整合後若是發現是抽象類不能實例 拋出異常
checkMergedBeanDefinition(mbd, beanName, args);
// 獲取Bean定義所需的依賴並逐一初始化填充
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 判斷是否循環依賴
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 註冊依賴的Bean
registerDependentBean(dep, beanName);
try {
// 遞歸調用生成所需依賴的Bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 若是是單例的話
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 若是是原型的話
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } // 非單例和原型 範圍的狀況 else { String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } } }); bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider " + "defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } // 檢測實例Bean的類型和所需類型是否一致 if (requiredType != null && bean != null && !requiredType.isInstance(bean)) { try { return getTypeConverter().convertIfNecessary(bean, requiredType); } catch (TypeMismatchException ex) { if (logger.isDebugEnabled()) { logger.debug("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; } 複製代碼
文章篇幅有限,IOC整個的建立過程仍是比較冗長的,但願讀者看完文章對IOC的建立過程有一個主幹脈絡的思路以後仍是須要翻開源碼進行解讀,其實閱讀源碼並不難,由於Spring的代碼註釋都挺健全,若是遇到不清楚的稍微google一下就知道了。建議讀者本身試着一步一步的分析IOC過程的源碼。