3、Spring原始碼分析3之載入Bean
阿新 • • 發佈:2019-10-10
1、Bean的載入
// 前面兩篇已經分析了讀取配置檔案,並註冊BeanDefinition
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beanFactory.xml"));
// 這篇分析載入Bean
MyTestBean bean = bf.getBean("myTestBean", MyTestBean.class);
public <T> T getBean(String name, Class<T> requiredType) throws BeansException { return doGetBean(name, requiredType, null, false); }
protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly){ //轉換對應的beanName,先是去除FactoryBean的修飾符&,取指定alias所表示的最終beanName(如果存在的話) final String beanName = transformedBeanName(name); Object bean; //1.檢查快取中或者例項工廠中是否有對應的例項 Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { //2.返回對應的例項,如附錄中的FactoryBean例子,上面的sharedInstance是CarFactoryBean的例項,但是 //實際應當返回Car例項,因此在該方法中會做處理 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { //只有在單例情況下才嘗試解決迴圈依賴,否則直接拋異常 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } //如果beanDefinitionMap不存在beanName則嘗試從parentBeanFactory中尋找 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { String nameToLookup = originalBeanName(name); if (args != null) { return (T) parentBeanFactory.getBean(nameToLookup, args); }else { return parentBeanFactory.getBean(nameToLookup, requiredType); } } if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); //如果存在依賴則需要遞迴例項化依賴的bean String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dependsOnBean : dependsOn) { getBean(dependsOnBean); registerDependentBean(dependsOnBean, beanName); } } //3.獲取單例的bean if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { 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); try { 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); } catch (IllegalStateException ex) { } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) { try { return getTypeConverter().convertIfNecessary(bean, requiredType); } catch (TypeMismatchException ex) {} } return (T) bean; }
步驟1:
Object sharedInstance = getSingleton(beanName);
public Object getSingleton(String beanName) { //引數true表示設定允許早期依賴 return getSingleton(beanName, true); } protected Object getSingleton(String beanName, boolean allowEarlyReference) { //首先嚐試從快取中載入,singletonObjects = new ConcurrentHashMap<String, Object>(64); Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { //如果為空,則鎖定全域性變數進行處理 synchronized (this.singletonObjects) { //如果此bean正在載入則不處理 singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { //呼叫預先設定的getObject方法 singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return (singletonObject != NULL_OBJECT ? singletonObject : null); }
步驟2:
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
//驗證,若指定的name是工廠相關,以&開頭,又不是FactoryBean型別則驗證不通過
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)){
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
//是正常的bean直接返回,或者使用者想取的就是FactoryBean型別的bean(name以&開頭)則直接返回
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)){
return beanInstance;
}
Object object = null;
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
//從快取中獲取
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;
}
步驟3:獲取單例的bean
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
//全域性變數上鎖
synchronized (this.singletonObjects) {
//檢查快取中是否已經建立,如果為空才可以初始化
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//記錄載入狀態,關鍵的一步,將正在建立的bean放入singletonsCurrentlyInCreation,用於檢測迴圈依賴
beforeSingletonCreation(beanName);
try {
//通過傳入的singletonFactory例項化bean,回撥
singletonObject = singletonFactory.getObject();
}
catch (BeanCreationException ex) {}
finally {
//和記錄載入狀態相反,建立完成之後移除正在載入的記錄
afterSingletonCreation(beanName);
}
//建立完成之後,將其放入快取中,並刪除載入bean過程中的各種輔助狀態
addSingleton(beanName, singletonObject);
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.containsKey(beanName) &&
this.singletonsCurrentlyInCreation.put(beanName, Boolean.TRUE) != null) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
//上述回撥進行bean的建立
singletonObject = singletonFactory.getObject();
public Object getObject() throws BeansException {
return createBean(beanName, mbd, args);
}
protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args){
try {
//1.處理lookup-method和replace-method,bean例項化的時候若檢測到有methodOverides屬性,會動態地
//為當前bean生成代理並使用對應的攔截器為bean做增強處理,相關邏輯在bean例項化時會分析,此處僅是做下校驗
mbd.prepareMethodOverrides();
}
try {
//給BeanPostProcessors一個機會來返回代理替代真正的例項
Object bean = resolveBeforeInstantiation(beanName, mbd);
//短路,若經過處理的bean不為空,則直接返回代理的bean,AOP功能就是基於這裡的判斷,後面分析
if (bean != null) {
return bean;
}
}
//進行常規bean的建立
Object beanInstance = doCreateBean(beanName, mbd, args);
return beanInstance;
}
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
BeanWrapper instanceWrapper = null;
//如果是單例要清除快取
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
//例項化Bean,將BeanDefinition轉換為BeanWrapper,該過程比較複雜
//a、存在工廠方法就使用工廠方法初始化
//b、若有多個建構函式,則根據引數鎖定建構函式初始化
//c、若既不存在工廠方法,也不存在帶參建構函式,則使用預設建構函式初始化
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//...省略後續程式碼,先分析createBeanInstance
}
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
//解析beanClass
Class<?> beanClass = resolveBeanClass(mbd, beanName);
//1.若存在工廠方法,就使用工廠方法初始化並返回,工廠方法用例見附錄2
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
//若不存在工廠方法則使用建構函式初始化
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
//如果已經解析快取了,則直接呼叫建構函式初始化
if (resolved) {
if (autowireNecessary) {
//使用帶參建構函式初始化
return autowireConstructor(beanName, mbd, null, null);
}
else {
//使用預設建構函式
return instantiateBean(beanName, mbd);
}
}
//需要根據引數解析建構函式
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
//帶參建構函式
return autowireConstructor(beanName, mbd, ctors, args);
}
//預設建構函式
return instantiateBean(beanName, mbd);
}
1、使用工廠方法初始化
經過一系列處理,使用工廠方法初始化最終會呼叫到此處
beanInstance = beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, beanFactory, factoryBean, factoryMethodToUse, argsToUse);
public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner,
Object factoryBean, final Method factoryMethod, Object[] args) {
ReflectionUtils.makeAccessible(factoryMethod);
//使用反射呼叫工廠方法
return factoryMethod.invoke(factoryBean, args);
}
public Object invoke(Object obj, Object... args){
MethodAccessor ma = methodAccessor;
//debug時發現此處會呼叫工廠方法
return ma.invoke(obj, args);
}
public static FactoryMethodBean getInstance(){
return new FactoryMethodBean();
}
2、使用帶參建構函式初始化,無參建構函式更簡單,因為不需要定位建構函式,建立物件類似使用帶參建構函式初始化,最終會呼叫到此處.
beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner,
final Constructor<?> ctor, Object[] args) {
//如果有需要覆蓋或者動態替換的方法則使用CGLIB動態代理,可以在建立代理的同時動態將方法織如類中
if (beanDefinition.getMethodOverrides().isEmpty()) {
//如果沒有直接呼叫反射來構造例項物件
return BeanUtils.instantiateClass(ctor, args);
}
else {
return instantiateWithMethodInjection(beanDefinition, beanName, owner, ctor, args);
}
}
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
try {
ReflectionUtils.makeAccessible(ctor);
//呼叫反射進行構造物件
return ctor.newInstance(args);
}
}
附錄
1、FactoryBean的使用
public interface FactoryBean<T> {
//核心方法,讓實現類實現的,返回由FactoryBean建立的bean例項
T getObject() throws Exception;
Class<?> getObjectType();
boolean isSingleton();
}
public class Car {
private int maxSpeed;
private String brand;
private double price;
public int getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
public class CarFactoryBean implements FactoryBean<Car>{
private String carInfo;
public Car getObject() throws Exception {
Car car = new Car();
String[] infos = carInfo.split(",");
car.setBrand(infos[0]);
car.setMaxSpeed(Integer.valueOf(infos[1]));
car.setPrice(Double.valueOf(infos[2]));
return car;
}
public Class<?> getObjectType() {
return Car.class;
}
public boolean isSingleton() {
return true;
}
public String getCarInfo() {
return carInfo;
}
public void setCarInfo(String carInfo) {
this.carInfo = carInfo;
}
}
<bean id="car" class="com.lwh.spring.bean.CarFactoryBean">
<property name="carInfo" value="超級跑車,400,200000"/>
</bean>
當呼叫getBean時,Spring通過反射機制發現CarFactoryBean實現了FactoryBean介面,這時Spring容器就呼叫介面方法getObject()
返回Bean例項.如果希望獲取CarFactoryBean的例項,需要使用getBean(beanName)方法時在beanName前顯示加上&字首,例如
getBean(“&car”).
2、工廠方法factory-method
public class FactoryMethodBean {
private String str = "lwh sayHello";
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public static FactoryMethodBean getInstance(){
return new FactoryMethodBean();
}
}
<bean id="factoryMethodBean" class="com.lwh.spring.factory.FactoryMethodBean" factory-method="getInstance