Spring 的 getBean 方法源碼解析

文本將從如下幾個方面介紹

相關文章java

FactoryBean 接口spring

BeanFactory 接口 sql

BeanFactory 接口 和 FactoryBean 接口的區別數組

getBean 方法的源碼解析緩存

Spring 循環依賴的解決方式mybatis

相關文章

Spring 中 bean 註冊的源碼解析app

Spring bean 建立過程源碼解析框架

前言

在文章 Spring 中 bean 註冊的源碼解析 和 Spring bean 建立過程源碼解析 瞭解了 bean 的註冊和建立過程,當經過 getBean 方法來獲取對應 bean 的時候,會是如何的呢?下面就來看看 getBean 方法的內部實現。在進入 getBean 方法內部以前,先來看看 FactoryBean 這個接口,由於在 getBean 方法內部會對該接口的實現類進行另外的處理。ide

FactoryBean

這個接口和 BeanFactory 接口很是的像,可是做用卻大相徑庭,先來看看 javadoc 文檔的定義,大體意思就是:若是某個 bean 實現了這個接口,經過 getBean 方法來獲取 bean 的時候,並非返回本身的實例,而是返回其 getObject() 方法的返回值;此外 FactoryBeans 能夠支持 singletons 和  prototypes 模式。它的源碼以下,只有 三個 方法:工具

public interface FactoryBean<T> {
	// 返回 bean 的實例,即調用 getBean 方法獲取到的實例就是該方法的返回值 
	T getObject() throws Exception;

	// 返回 bean 的類型
	Class<?> getObjectType();

	// 該 bean 是不是單例模式
	boolean isSingleton();
}

那麼這個 FactoryBean 接口有什麼用呢?經過 Spring bean 建立過程源碼解析 知道,bean 的實例化就是使用反射和CGLIB來實現的,可是在某些狀況下,實例化 Bean 過程比較複雜,若是按照傳統的方式,則須要在配置文件 <bean> 中提供大量的配置信息。配置方式的靈活性是受限的,這時採用編碼的方式可能會獲得一個簡單的方案。因此,用戶能夠經過實現該接口定製實例化 Bean 的邏輯。

先來看一個栗子,如今有個 User 對象,傳統的方式,在配置文件中配置以下:

public class User {

    private String name;
    private int age;
    private int sex;
    private double money;
    private String job;

    // setter / getter / toString
}
<bean id="user" class="main.tsmyk.pojo.User">
	<property name="name" value="zhangsan"/>
	<property name="age" value="20"/>
	<property name="job" value="java"/>
	<property name="money" value="10000"/>
	<property name="sex" value="1"/>
</bean>

測試:

ApplicationContext context = new ClassPathXmlApplicationContext("myspring.xml");
User user = (User) context.getBean("user");
System.out.println(user);

結果:User{name='zhangsan', age=20, sex=1, money=10000.0, job='java'}

從打印的結果能夠看到 User 對象的屬性都被附上了值。

可是,若是 User 對象的屬性不少,不想寫不少的 <property> 標籤,則能夠經過 FactoryBean 接口來實現,在該接口內部,按照必定的規則來解析 User 對象的屬性並賦值。以下所示:

public class UserFactoryBean implements FactoryBean<User> {

    private String user;

    @Override
    public User getObject() throws Exception {
        User user = new User();
        String[] userInfos = this.user.split(";");
        user.setName(userInfos[0]);
        user.setAge(Integer.parseInt(userInfos[1]));
        user.setJob(userInfos[2]);
        user.setMoney(Double.parseDouble(userInfos[3]));
        user.setSex(Integer.parseInt(userInfos[4]));
        return user;
    }

    @Override
    public Class<User> getObjectType() {
        return User.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }

    public String getUser() {
        return user;
    }
	public void setUser(String user) {
        this.user = user;
    }
}

在該類的 getObject 方法內部對 User 對象的屬性進行解析並賦值,經過 getBean 方法獲取 bean 的時候,獲得的就是 getObject 方法返回的 User 對象,配置以下:

<bean id="userFactory" class="main.tsmyk.beans.UserFactoryBean">
	<property name="user" value="zhangsan;20;java;10000;1"/>
</bean>

測試:

ApplicationContext context = new ClassPathXmlApplicationContext("myspring.xml");
User user1 = (User) context.getBean("userFactory");
System.out.println(user1);

結果:User{name='zhangsan', age=20, sex=1, money=10000.0, job='java'}

能夠看到和上面傳統的方式是同樣的。也驗證了 getBean 方法獲取到的是 getObject 方法的返回值,而不是 FactoryBean 實例自己;可是,若是就想獲取到 FactoryBean 的實例自己,也是能夠的,在 bean 的名字前加 & 符號就能夠了,即 getBean("&userFactory");

測試:

ApplicationContext context = new ClassPathXmlApplicationContext("myspring.xml");
UserFactoryBean userBean = (UserFactoryBean) context.getBean("&userFactory");
System.out.println(userBean.getUser());

結果:zhangsan;20;java;10000;1

敲黑板:因此說,經過 getBean(String beanName) 方法來獲取實例的時候,beanName 有多是以 & 開頭的,若是 beanName & 開頭,就表示處理的是 FactoryBean 接口

Spring 自身也提供了 FactoryBean  接口的不少實現,如 JndiObjectFactoryBean 類:

public class JndiObjectFactoryBean extends JndiObjectLocator implements FactoryBean<Object>, BeanFactoryAware, BeanClassLoaderAware {
    private Object jndiObject;
    // 其餘複雜的計算,爲 jndiObject 賦值
	@Override
	public Object getObject() {
		return this.jndiObject;
	}
}

咱們熟知的第三方 ORM 框架 Mybatis 也提供了該接口的實現 SqlSessionFactoryBean :

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
	// 其餘配置
</bean>
public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
  private SqlSessionFactory sqlSessionFactory;
  @Override
  public SqlSessionFactory getObject() throws Exception {
    if (this.sqlSessionFactory == null) {
      afterPropertiesSet();
    }

    return this.sqlSessionFactory;
  }
  // 其餘方法
}

因此經過 getBean 方法獲取的時候,獲得的是 SqlSessionFactory 而不是 SqlSessionFactoryBean

BeanFactory

如今來看看和 FactoryBean 很類似的一個接口 BeanFactory BeanFactory 它是 Spring  IOC 容器的核心接口,它定義了 容器的主要功能,如建立 bean,獲取 bean 等,它是用來管理 bean 的,即它是用來 實例化、定位、配置應用程序中的對象及創建這些對象間的依賴關係的。它的源碼以下:

public interface BeanFactory {

	String FACTORY_BEAN_PREFIX = "&";
	Object getBean(String name) throws BeansException;
	<T> T getBean(String name, Class<T> requiredType) throws BeansException;
	Object getBean(String name, Object... args) throws BeansException;
	<T> T getBean(Class<T> requiredType) throws BeansException;
	<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
	boolean containsBean(String name);
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
	boolean isTypeMatch(String name, ResolvableType typeToMatch);
	boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
	Class<?> getType(String name) throws NoSuchBeanDefinitionException;
	String[] getAliases(String name);
}

能夠看到定義了容器的基本功能,注意它有一個屬性 FACTORY_BEAN_PREFIX = "&" 就是用來表示 FactoryBean 接口的 beanName 的前綴。

總結

到這裏,經過源碼就能夠看到,雖然  FactoryBean 和 BeanFactory 很像,但它們的做用徹底不一樣,

FactoryBean 能夠看作一個工廠,用它來建立一些負責的 bean

BeanFactory 定義了 Spring 容器基本的功能,交由子類去實現,用於管理 bean

getBean 方法

User user = (User) beanFactory.getBean("user");

@Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}

	@Override
	public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
		return doGetBean(name, requiredType, null, false);
	}

	@Override
	public Object getBean(String name, Object... args) throws BeansException {
		return doGetBean(name, null, args, false);
	}

接下來看下 doGetBean 方法:

protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
		throws BeansException {
    // 提取對應的 beanName,處理別名和FactoryBean接口的實現類,即 beanName 以 & 開頭
	final String beanName = transformedBeanName(name);
	Object bean;
    // 嘗試從緩存中或者ObjectFactory中獲取
	Object sharedInstance = getSingleton(beanName);
	if (sharedInstance != null && args == null) {
		if (isSingletonCurrentlyInCreation(beanName)) {
			logger.debug("......");
		}
        // 這裏主要處理 FactoryBean,有時候並非返回實例自己,而是返回指定方法返回的實例
		bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
	}
    // 緩存中不存在該bean的實例
	else {
        // 這裏bean的做用域是原型模式,且存在循環依賴,出現循環依賴,則拋出異常
		if (isPrototypeCurrentlyInCreation(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
		BeanFactory parentBeanFactory = getParentBeanFactory();
        // 若是當前的的beanDefinitionMap即配置文件不包含該bean,則從parentBeanFactory 中查找
		if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
			String nameToLookup = originalBeanName(name);
			if (args != null) {
                // 這個 args 是 getBean(beanName, args...) 方法傳入的
				return (T) parentBeanFactory.getBean(nameToLookup, args);
			}
			else {
				return parentBeanFactory.getBean(nameToLookup, requiredType);
			}
		}
        // 若是不只僅是作類型檢查,則是建立bean,則進行標記,標記該bean以建立
		if (!typeCheckOnly) {
			markBeanAsCreated(beanName);
		}
        // 將配置文件中GenericBeanDefinition轉換爲RootBeanDefinition,若是beanName是子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("........");
				}
				registerDependentBean(dep, beanName);
				getBean(dep);
			}
		}
        //實例化 bean
		if (mbd.isSingleton()) {
            // 實例化單例的bean
			sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
				@Override
				public Object getObject() throws BeansException {					
					return createBean(beanName, mbd, args);
				});
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
		}
		else if (mbd.isPrototype()) {
            // 實例化原型的bean
			Object prototypeInstance = null;
			try {
				beforePrototypeCreation(beanName);
				prototypeInstance = createBean(beanName, mbd, args);
			}
			finally {
				afterPrototypeCreation(beanName);
			}
			bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
		}
		else {
            // 指定的 score 上實例化bean
			String scopeName = mbd.getScope();
			final Scope scope = this.scopes.get(scopeName);
			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);
				}
			}
		}
	}
    // 處理參數類型的轉換
	if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
		return getTypeConverter().convertIfNecessary(bean, requiredType);
	}
	return (T) bean;
}

從 上述的代碼能夠看到,doGetBean 方法流程是很清晰的,每一步都使用對應的方法進行處理,它的流程主要以下:

1. 處理 beanName,爲何要處理 beanName呢,由於 bean 是能夠有別名的,且,在上面介紹 FactoryBean 接口的時候,獲取該 bean 的時,須要加上 & 前綴,因此這裏要去掉&

2. 嘗試從緩存中加載該 bean,由於單例的 bean 只會加載一次,若是緩存中不存在該 bean,則會嘗試從 singletonFactories 中加載,這個 singletonFactories 是什麼呢? 在 Spring bean 建立過程源碼解析 知道, bean 在建立的時候可能會存在依賴注入的狀況,而在建立依賴 bean 的時候,爲了 避免循環依賴,那麼在建立該 bean 的時候,不等到 bean 建立完成就會把建立該 bean 的 ObjectFactory 放到 singletonFactories  緩存中,一旦下一個 bean 建立的時候,須要依賴上一個 bean 則直接從 singletonFactories   緩存中獲取該 ObjectFactory 來進行建立,好比 A 依賴 B,A --> B,如今建立 A 的實例 beanA,建立過程當中,就把建立 A 的 ObjectFactory 放到 singletonFactories   緩存中,如今發現 A 依賴於 B,則如今要去建立 B 的實例 beanB,當建立完 beanB 後纔會繼續建立 beanA;若是如今發現 B 也依賴於 A,B --> A,那麼在建立 beanB 的時候,也會先去建立 beanA,由於以前建立 A 的實例 beanA 的時候,已經把 A 的 ObjectFactory 放入到 緩存中了,如今直接去緩存中取出該 ObjectFactory 便可,試想一下,若是沒有事先把 A 的 ObjectFactory 放到緩存中,那麼在建立 B 的時候,先去建立 A ,建立 A  的時候發現依賴 B ,則又會去 建立 B,這樣就會形成循環依賴,就會實例化失敗。

因此 Spring 是經過這種方法是解決 bean 之間循環依賴的,可是僅僅是處理單例的循環依賴,原型或其餘的則會拋出異常。關於 bean 的建立能夠參考 Spring bean 建立過程源碼解析

3. 建立 bean
    3.1 從父類查找 bean 
    3.2 將 GenericBeanDefinition 轉換爲 RootBeanDefinition,由於從配置文件加載 bean 的時候,是以 GenericBeanDefinition  方式保存的
    3.3 處理依賴
    3.4 建立 單例的 bean 
    3.5 建立 原型的 bean 
    3.6 建立其餘 score 做用於的 bean
    3.7 參數類型的轉換

4. 處理 FactoryBean 接口的 bean

流程是否是很清晰,再經過流程圖來看更清晰:

下面看看每一個部分。

1. 提取 beanName

當經過 getBean 方法獲取 bean 的時候,bean 的 name 是能夠以  & 開頭的,即獲取 FactoryBean 實例自己,此外,bean 還有別名,一個 bean 能夠有多個別名等,全部在這裏首先要提取 bean 的名稱,即 方法 transformedBeanName:

final String beanName = transformedBeanName(name);

protected String transformedBeanName(String name) {
    String beanName = BeanFactoryUtils.transformedBeanName(name);
	return canonicalName(beanName);
}

// 使用工具類 BeanFactoryUtils 來轉名字
public static String transformedBeanName(String name) {
	String beanName = name;
    // 若是 beanName 以 & 開頭,則去掉 &
	while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
		beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
	}
    // 返回去掉 & 後的 beanName
	return beanName;
}

// 返回原始的bean的名字,解決別名
public String canonicalName(String name) {
	String canonicalName = name;
	String resolvedName;
    // while 循環,由於 bean 的別名能夠有多個
	do {
		resolvedName = this.aliasMap.get(canonicalName);
		if (resolvedName != null) {
			canonicalName = resolvedName;
		}
	}
	while (resolvedName != null);
	return canonicalName;
}

2. 嘗試從緩存中獲取 bean 實例

Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
    // 處理 FactoryBean
	bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

// 獲取 bean
public Object getSingleton(String beanName) {
	return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 從緩存中獲取bean,該緩存singletonObjects用來存放已經建立完畢的bean的實例
	Object singletonObject = this.singletonObjects.get(beanName);
    // 若是緩存中沒有,且該 bean 正在建立
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		synchronized (this.singletonObjects) { 
            // 從正在建立bean的緩存中獲取,該 earlySingletonObjects 緩存是用來存放正在建立且尚未建立完畢的bean
			singletonObject = this.earlySingletonObjects.get(beanName);
            // 若是此時仍是獲取不到實例,且容許從ObjectFactory中獲取,解決循環引用
			if (singletonObject == null && allowEarlyReference) {
                // 從 ObjectFactory 中獲取對應的工廠,使用工廠建立建立對象,由於以前在建立該bean的時候且尚未建立完畢的時候,已經把該bean的 ObjectFactory 放入到緩存中
				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                // 獲取到工廠以後,進行建立bean的實例,並放入到對應的緩存中
				if (singletonFactory != null) {
					singletonObject = singletonFactory.getObject();
					this.earlySingletonObjects.put(beanName, singletonObject);
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
    // 若是緩存中沒有,且該bean沒有正在建立,則直接返回 nul
	return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

在該方法裏面會嘗試解決循環依賴,該方法會涉及到 3 個 map 類型的緩存:

  1. 緩存 singletonObjects 用來存放已經建立完畢的bean的實例
  2. 緩存 earlySingletonObjects 是用來存放正在建立且尚未建立完畢的bean
  3. 緩存 ObjectFactory 用來存放對應的工廠,由於以前在建立該bean的時候且尚未建立完畢的時候,已經把該bean的 ObjectFactory 放入到緩存中

因此上述方法的主要邏輯就是先從 singletonObjects 獲取實例,若是獲取不到,即該 bean 尚未建立;再從 earlySingletonObjects 獲取,若是獲取不到,即該bean沒有正在建立,再從 ObjectFactory 獲取對應的工廠來建立,若是到最後仍是獲取不到,則返回 null、

3. 處理 FactoryBean

獲取到 bean的實例後,須要處理 諸如 FactoryBean 和 factory-method 之類的方法,在後面從不一樣的 score 獲取到 bean 的實例後,都會執行該方法:

protected Object getObjectForBeanInstance(
		Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {

	// 若是 bean 的實例不是 FactoryBean 類型,便是通常的 bean ,能夠直接返回
    // 若是 beanName 是以 & 開頭,則也直接返回,由於 beanName 以 & 開頭,表示返回工廠實例自己
    // BeanFactoryUtils.isFactoryDereference : name != null && name.startsWith("&")
	if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
		return beanInstance;
	}

	Object object = null;
	if (mbd == null) {
        // 嘗試從 FactoryBean 緩存中獲取bean
		object = getCachedObjectForFactoryBean(beanName);
	}
	if (object == null) {
		// 到這裏,已經明確了 bean的實例必定是 FactoryBean 類型
		FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
		if (mbd == null && containsBeanDefinition(beanName)) {
			mbd = getMergedLocalBeanDefinition(beanName);
		}
		boolean synthetic = (mbd != null && mbd.isSynthetic());
		object = getObjectFromFactoryBean(factory, beanName, !synthetic);
	}
	return object;
}
// 經過 FactoryBean 來獲取 bean 實例
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    // 忽略了其餘代碼
    // doGetObjectFromFactoryBean -> factory.getObject(),返回的是 FactoryBean 的 getObject 方法的返回值
	object = doGetObjectFromFactoryBean(factory, beanName);
    return object;
}

4. 建立bean

通過了上述幾步,發現從獲取中還獲取不到實例的話,就會進行 bean 的實例化。當時在建立以前,若是該 bean 有依賴的 bean,則先會處理依賴的bean:

4.1 處理依賴的 bean

String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
	for (String dep : dependsOn) {
		if (isDependent(beanName, dep)) {
			throw new BeanCreationException("循環依賴異常");
		}
        // 註冊循環依賴
		registerDependentBean(dep, beanName);
		// 建立依賴的 bean
		getBean(dep); // return doGetBean(name);
	}
}

4.2 建立 bean 

if (mbd.isSingleton()) {
    // 建立單例的bean
	sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
		@Override
		public Object getObject() throws BeansException {
			return createBean(beanName, mbd, args);
		}
	});
	bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
    // 建立原型的bean 
	Object prototypeInstance = null;
	try {
		beforePrototypeCreation(beanName);
		prototypeInstance = createBean(beanName, mbd, args);
	}
	finally {
		afterPrototypeCreation(beanName);
	}
	bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
    // 建立其餘score的bean
	String scopeName = mbd.getScope();
	final Scope scope = this.scopes.get(scopeName);
	Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
	    public Object getObject() throws BeansException {
		beforePrototypeCreation(beanName);
		try {
			return createBean(beanName, mbd, args);
		}
		finally {
			afterPrototypeCreation(beanName);
		});
		bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}

單例的 bean和其餘score的bean的建立能夠參考 Spring bean 建立過程源碼解析 的 createBean 方法。

下面來看看建立原型的bean的過程:

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
	RootBeanDefinition mbdToUse = mbd;
	// 解析 class 
	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}

	// 處理 lookup-method 和 replace-method 屬性,在 「Spring 中 bean 註冊的源碼解析「 從已經解析過
	mbdToUse.prepareMethodOverrides();
	// 在該方法裏面會執行前置處理器和後置處理器
	Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    // 若是應用前置處理和後置處理器改變了bean,就直接返回,AOP功能就在此實現
	if (bean != null) {
		return bean;
	}
    // 正真建立bean
	Object beanInstance = doCreateBean(beanName, mbdToUse, args);
	return beanInstance;
}

// 應用前置處理器和後置處理器
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
	Object bean = null;
	Class<?> targetType = determineTargetType(beanName, mbd);
	if (targetType != null) {
        // 前置處理器
		bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
		if (bean != null) {
            // 後置處理器 
			bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
		}
	}
    // 省略其餘代碼
	return bean;
}

// 前置處理器
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
	for (BeanPostProcessor bp : getBeanPostProcessors()) {
		if (bp instanceof InstantiationAwareBeanPostProcessor) {
			InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
			Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
			if (result != null) {
				return result;
			}
		}
	}
	return null;
}
// 後置處理器
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
		throws BeansException {
	Object result = existingBean;
	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
		result = beanProcessor.postProcessAfterInitialization(result, beanName);
		if (result == null) {
			return result;
		}
	}
	return result;
}

5. 類型轉換

通過了上述的步驟以後,就會獲得一個 bean 的實例,不管這個bean是單例的仍是原型的,仍是其餘的score的,總之到這裏就已經獲得了 bean 的實例,獲得實例以後,咱們須要進行類型的轉換,即 若是 bean 是一個 String,可是 requiredType 爲 Integer ,則就須要進行類型的轉換。

if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
	return getTypeConverter().convertIfNecessary(bean, requiredType);
}

// 獲取類型轉換器
public TypeConverter getTypeConverter() {
	TypeConverter customConverter = getCustomTypeConverter();
	if (customConverter != null) {
		return customConverter;
	}
	else {
		SimpleTypeConverter typeConverter = new SimpleTypeConverter();
		typeConverter.setConversionService(getConversionService());
		registerCustomEditors(typeConverter);
		return typeConverter;
	}
}

// 類型的轉換
public <T> T convertIfNecessary(Object value, Class<T> requiredType, Field field){
	return doConvert(value, requiredType, null, field);
}

private <T> T doConvert(Object value, Class<T> requiredType, MethodParameter methodParam, Field field){
	if (field != null) {
		return this.typeConverterDelegate.convertIfNecessary(value, requiredType, field);
	}
	else {
		return this.typeConverterDelegate.convertIfNecessary(value, requiredType, methodParam);
	}
}

// 正真類型的轉換
public <T> T convertIfNecessary(String propertyName, Object oldValue, Object newValue,
	Class<T> requiredType, TypeDescriptor typeDescriptor) throws IllegalArgumentException {
    // 自定義轉換器
    PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);
    ConversionFailedException conversionAttemptEx = null;
    ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
    if (editor == null && conversionService != null && newValue != null && typeDescriptor != null) 
    {
	    TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
	    if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
		    return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
	    }
     }
   }
   // 省略其餘代碼
    if (requiredType != null) {
    if (convertedValue != null) {
        // 類型爲 class
		if (Object.class == requiredType) {
			return (T) convertedValue;
		}
        // 類型爲數組
		else if (requiredType.isArray()) {
			if (convertedValue instanceof String && Enum.class.isAssignableFrom(requiredType.getComponentType())) {convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
			}
			return (T) convertToTypedArray(convertedValue, propertyName, requiredType.getComponentType());
		}
        // 類型爲集合
		else if (convertedValue instanceof Collection) {
			convertedValue = convertToTypedCollection((Collection<?>) convertedValue, propertyName, requiredType, typeDescriptor);
			standardConversion = true;
		}
        // 類型爲 map
		else if (convertedValue instanceof Map) {
			convertedValue = convertToTypedMap( (Map<?, ?>) convertedValue, propertyName, requiredType, typeDescriptor);
			standardConversion = true;
		}
		if (convertedValue.getClass().isArray() && Array.getLength(convertedValue) == 1) {
			convertedValue = Array.get(convertedValue, 0);
			standardConversion = true;
		}
        // String
		if (String.class == requiredType && ClassUtils.isPrimitiveOrWrapper(convertedValue.getClass())) {
			return (T) convertedValue.toString();
		}
        // String
		else if (convertedValue instanceof String && !requiredType.isInstance(convertedValue)) {
			if (conversionAttemptEx == null && !requiredType.isInterface() && !requiredType.isEnum()) {
				Constructor<T> strCtor = requiredType.getConstructor(String.class);
				return BeanUtils.instantiateClass(strCtor, convertedValue);
			}
			String trimmedValue = ((String) convertedValue).trim();
			if (requiredType.isEnum() && "".equals(trimmedValue)) {
				return null;
			}
			convertedValue = attemptToConvertStringToEnum(requiredType, trimmedValue, convertedValue);
			standardConversion = true;
		}
        // number
		else if (convertedValue instanceof Number && Number.class.isAssignableFrom(requiredType)) {
			convertedValue = NumberUtils.convertNumberToTargetClass(
					(Number) convertedValue, (Class<Number>) requiredType);
			standardConversion = true;
		}
	}
	else {
		if (javaUtilOptionalEmpty != null && requiredType == javaUtilOptionalEmpty.getClass()) {
			convertedValue = javaUtilOptionalEmpty;
		}
	}
    // 省略其餘代碼
    return (T) convertedValue;
}

 到這裏 經過 getBean 就能獲取到一個正確的 bean 了,

以上就是 getBean 方法的邏輯了,主要是須要知道 還能夠經過 FactoryBean 來建立 bean,beanName 還能夠是以 & 開頭。 

相關文章
相關標籤/搜索