亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring中加載Bean的使用方法

發布時間:2021-06-26 09:39:32 來源:億速云 閱讀:161 作者:chen 欄目:大數據

這篇文章主要講解了“Spring中加載Bean的使用方法”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Spring中加載Bean的使用方法”吧!

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);

Spring中加載Bean的使用方法

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、使用工廠方法初始化
經過一系列處理,使用工廠方法初始化最終會調用到此處

Spring中加載Bean的使用方法

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、使用帶參構造函數初始化,無參構造函數更簡單,因為不需要定位構造函數,創建對象類似使用帶參構造函數初始化,最終會調用到此處.

Spring中加載Bean的使用方法

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"/>

感謝各位的閱讀,以上就是“Spring中加載Bean的使用方法”的內容了,經過本文的學習后,相信大家對Spring中加載Bean的使用方法這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

沁水县| 乳源| 江陵县| 长寿区| 通化市| 桓仁| 商丘市| 崇仁县| 靖宇县| 百色市| 张家港市| 治多县| 镇赉县| 桦南县| 洪江市| 玉溪市| 阿克苏市| 溧水县| 宁陵县| 柳州市| 女性| 晋州市| 静安区| 新建县| 伊金霍洛旗| 高安市| 定南县| 西乌珠穆沁旗| 中牟县| 仙游县| 张家港市| 环江| 周宁县| 金昌市| 石城县| 克拉玛依市| 启东市| 丰都县| 房山区| 屏南县| 珠海市|