欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談一下Spring中的createBean

 更新時間:2022年07月22日 11:02:21   作者:BaldHead  
createBean是創(chuàng)建Bean的主要方法, 該方法位于:AbstractBeanFactory的doGetBean方法中的createBean調(diào)用。本文就來淺談一下Spring中的createBean?,感興趣的可以了解一下

找到BeanClass并且加載類

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		if (logger.isTraceEnabled()) {
			logger.trace("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;

		// Make sure bean class is actually resolved at this point, and
		// clone the bean definition in case of a dynamically resolved Class
		// which cannot be stored in the shared merged bean definition.
		// 找到需要創(chuàng)建 Bean 對應(yīng)的 Class
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}
  .......省略與此步驟無關(guān)的代碼
}

注意:上面代碼中的 resolveBeanClass(mbd, beanName) 方法,就是去查找BeanClass的,下面看看 resolveBeanClass 方法的代碼

@Nullable
protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)
      throws CannotLoadBeanClassException {

   try {
      // 判斷 BeanDefinition 中的 beanClass 屬性是不是 Class 類型的
      if (mbd.hasBeanClass()) {
         return mbd.getBeanClass();
      }
      // 執(zhí)行搜索 Bean class
      return doResolveBeanClass(mbd, typesToMatch);
   }  ...省略catch 代碼
   }
}

注意代碼中有一個 mbd.hasBeanClass() 的判斷, 這個地方比較有迷惑性,并不是判斷beanClass屬性是否存在,而是判斷

beanClass 屬性是不是屬于 Class類型的,因?yàn)樵趕pring最開始的掃描過程中,給BeanDefiniton 中 beanClass 屬性存入的是對應(yīng) BeanDefinition 的類名稱,下面是 hasBeanClass() 方法的代碼:

public boolean hasBeanClass() {

   // 判斷 BeanDefinition 中的 beanClass 屬性是不是屬于 Class 的
   // 因?yàn)樽铋_始的時候存入的是 BeanDefinition 對應(yīng)的類的類名
   return (this.beanClass instanceof Class);
}

如果判斷 beanClass 屬性 是一個CLass 對象則直接返回,否則進(jìn)入doResolceBeanClass(mad, typesToMatch) 方法

private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
      throws ClassNotFoundException {

   // 獲取類加載器
   ClassLoader beanClassLoader = getBeanClassLoader();
   ClassLoader dynamicLoader = beanClassLoader;
   boolean freshResolve = false;

   .... 省略代碼
     
   // 這里就是拿的 RootBeanDefinition 中的 beanClass屬性
   String className = mbd.getBeanClassName();
   if (className != null) {
      // 解析 spring 自己定義的表達(dá)式---沒有去了解
      Object evaluated = evaluateBeanDefinitionString(className, mbd);
      if (!className.equals(evaluated)) {
         // A dynamically resolved expression, supported as of 4.2...
         if (evaluated instanceof Class) {
            return (Class<?>) evaluated;
         } else if (evaluated instanceof String) {
            className = (String) evaluated;
            freshResolve = true;
         } else {
            throw new IllegalStateException("Invalid class name expression result: " + evaluated);
         }
      }
      if (freshResolve) {
         // When resolving against a temporary class loader, exit early in order
         // to avoid storing the resolved Class in the bean definition.
         if (dynamicLoader != null) {
            try {
               // 加載類,當(dāng)前 需要創(chuàng)建的 Bean 的 Class文件
               return dynamicLoader.loadClass(className);
            } catch (ClassNotFoundException ex) {
               if (logger.isTraceEnabled()) {
                  logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);
               }
            }
         }
        	// 內(nèi)部 使用了 Class.forName() 去加載這個類:Class.forName(name, false, clToUse);
         return ClassUtils.forName(className, dynamicLoader);
      }
   }
   // 定期解析,將結(jié)果緩存在 BeanDefinition 中
   // Resolve regularly, caching the result in the BeanDefinition...
   return mbd.resolveBeanClass(beanClassLoader);
}

首先我們注意到方法進(jìn)入時就有一個獲取BeanClassLoader的方法 getBeanClassLoader(),最終該方法的代碼是如下:

@Nullable
public static ClassLoader getDefaultClassLoader() {
   ClassLoader cl = null;
   try {
      // 獲取當(dāng)前線程的類加載器,可以設(shè)置的 Thread.currentThread().setContextClassLoader();
      cl = Thread.currentThread().getContextClassLoader();
   }
   catch (Throwable ex) {
      // Cannot access thread context ClassLoader - falling back...
   }
  // 使用當(dāng)前類的加載器去加載,有可能返回空,因?yàn)?lib 下面的 jar包使用 bootstrap 類加載器去加載的
   if (cl == null) {
      // No thread context class loader -> use class loader of this class.
      cl = ClassUtils.class.getClassLoader();
      if (cl == null) {
         // getClassLoader() returning null indicates the bootstrap ClassLoader
         try {
            // 獲取系統(tǒng)的加載器
            cl = ClassLoader.getSystemClassLoader();
         }
         catch (Throwable ex) {
            // Cannot access system ClassLoader - oh well, maybe the caller can live with null...
         }
      }
   }
   return cl;
}

就是拿到類加載器,最終就是使用當(dāng)前的類加載器,去加載mbd.getBeanClassName()方法拿出來的類名稱className

這樣將 BeanClass 文件就已經(jīng)被加載了,緊接著就是進(jìn)入實(shí)例化,在實(shí)例化前,還有一個步驟就是:實(shí)例化前

實(shí)例化前

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

	...... 省略上一步驟的代碼

   try {
      // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
      // 實(shí)例化前  InstantiationAwareBeanPostProcessor  使用的是這個 BeanPostprocessor
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      // 如果實(shí)例化前,由自己創(chuàng)建類對象則直接返回
      if (bean != null) {
         return bean;
      }
   }
  	// doCreateBean 執(zhí)行創(chuàng)建bean的方法,此方法中就會去實(shí)例化對象
  Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		... 省略日志打印
			return beanInstance;
  ..... 省略此步驟無關(guān)代碼
}

這里主要關(guān)注的就是實(shí)例化前的 InstantiationAwareBeanPostProcessor 接口,接口中有三個默認(rèn)的方法,這里只討論,postProcessBeforeInstantiation(Class<?> beanClass, String beanName) 初始化前的方法

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
	@Nullable
	default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		return null;
	}
  .... 省略另外兩個方法
}

該方法的執(zhí)行時機(jī)就是在實(shí)例化前,從給出的createBean方法源碼中可以體現(xiàn)出來,這里就給了我們許多的操作空間。

resolveBeforeInstantiation(beanName, mbdToUse); 在這個方法里面就回去執(zhí)行初始化前的調(diào)用:

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
   Object bean = null;
   if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
      // Make sure bean class is actually resolved at this point.
      if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
         Class<?> targetType = determineTargetType(beanName, mbd);
         if (targetType != null) {
            // 在實(shí)例化前應(yīng)用BeanPostProcessor
            bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
            if (bean != null) {
               // 初始化后的 BeanPostProcessor
               bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
            }
         }
      }
      mbd.beforeInstantiationResolved = (bean != null);
   }
   return bean;
}

可以看到在初始化前調(diào)用之后判斷了一次 返回的 bean對象是不是空,因?yàn)樵诔跏蓟胺椒ㄖ薪o傳入BeanClass 對象,在此之前就已經(jīng)給 beanClass 賦值過了,這里我們可以自己去創(chuàng)建一個對象返回,如果是這樣,表示不需要Spring來實(shí)例化了,并且后續(xù)的Spring依賴注入也不會進(jìn)行了,會跳過一些步驟,直接執(zhí)行初始化后這一步。在執(zhí)行實(shí)例化前這里還有一個小的知識,就是當(dāng)同時存在很多的實(shí)例化前 postProcessor ,只要一直行到 postProcessBeforeInstantiation 方法返回的bean不是空的的情況下,剩下所有的 初始化前postProcessor都不會在執(zhí)行了。

	protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    // 這里拿到的就是 InstantiationAwareBeanPostProcessor 類型的 postProcessor
		for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
			Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);
			// 因?yàn)檫@里是初始化前,所以在執(zhí)行到 beanPostprocessor 返回有對象的時候就直接返回,不會執(zhí)行后續(xù)的 InstantiationAwareBeanPostProcessor
			// 如果第一個處理器就返回了 對象實(shí)例,則不會再去執(zhí)行其他的 InstantiationAwareBeanPostProcessor
			if (result != null) {
				return result;
			}
		}
		return null;
	}

在for循環(huán)中 getBeanPostProcessorCache().instantiationAware方法拿到的就是,InstantiationAwareBeanPostProcessor類型的postProcessor,原因是:spring對postProcessor進(jìn)行了分類的:

下面進(jìn)入 doCreatebean() 中初始化的流程

實(shí)例化

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   // Instantiate the bean.
   // BeanWrapper:持有創(chuàng)建出來的Bean
   BeanWrapper instanceWrapper = null;
   // 判斷當(dāng)前的bean定義是否為單例
   if (mbd.isSingleton()) {
      // 有可能在本 Bean 創(chuàng)建之前就已經(jīng)把當(dāng)前 Bean 給創(chuàng)建出來了(比如在依賴注入過程中)
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);// 從工廠bean緩存中移除
   }// 不為空則  代表為 FactoryBean 已經(jīng)創(chuàng)建過,存在緩存中
   if (instanceWrapper == null) {
      /**
       * 創(chuàng)建bean的實(shí)例,默認(rèn)使用無參構(gòu)造器
       * 實(shí)例化但是并未初始化,就是沒有給bean的屬性復(fù)制
       * 組建的原始對象就創(chuàng)建了
       */
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   Object bean = instanceWrapper.getWrappedInstance();
   Class<?> beanType = instanceWrapper.getWrappedClass();
   if (beanType != NullBean.class) {
      mbd.resolvedTargetType = beanType;
   }

   // Allow post-processors to modify the merged bean definition.
   // 允許(MergedBeanDefinitionPostProcessor)增強(qiáng)器修改合并的bean definition 修改BD信息
   synchronized (mbd.postProcessingLock) {
      if (!mbd.postProcessed) {
         try {
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
         }
         catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "Post-processing of merged bean definition failed", ex);
         }
         mbd.postProcessed = true;
      }
   }
  ...... 省略代碼 ......
}

createBeanInstance(beanName, mbd, args);此方法就是去創(chuàng)建 bean 的實(shí)例;

此處還有一個 應(yīng)用增強(qiáng)器 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)根據(jù)名稱可以知道這是一個操作BeanDefinition的增強(qiáng)器,可以去修改BeanDefinition中的屬性,但是注意這個的執(zhí)行時機(jī),是在 bean 實(shí)例化之后在執(zhí)行的,所以說現(xiàn)在修改 BeanDefiniton的有些屬性是無效的,比如beanClss屬性,因?yàn)閎ean已經(jīng)創(chuàng)建了。

此處的 PostProcessor的類型為:MergedBeanDefinitionPostProcessor

Supplier創(chuàng)建對象

首先判斷BeanDefinition中是否設(shè)置了Supplier,如果設(shè)置了則調(diào)用Supplier的get()得到對象。

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
   // 拿到bean 的 class  Make sure bean class is actually resolved at this point.
   Class<?> beanClass = resolveBeanClass(mbd, beanName);

   if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
            "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
   }
   // 定義bean的提供者  ,存在就使用提供者創(chuàng)建對象:這是一個函數(shù)式接口
   Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
   if (instanceSupplier != null) {
     	// 存在 bean 的提供者,則直接調(diào)用 Supplier 的 get() 方法拿到對象
			return obtainFromSupplier(instanceSupplier, beanName);
   }
 // 使用工廠方法、例如:@Bean注解放在方法上,返回值注入容器,spring 會認(rèn)為這是一個工廠方法
		if (mbd.getFactoryMethodName() != null) {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		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);
			}
		}

		// 后置處理器 SmartInstantiationAwareBeanPostProcessor 有機(jī)會決定在創(chuàng)建對象錢使用那個構(gòu)造器 Candidate constructors for autowiring?
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			return autowireConstructor(beanName, mbd, ctors, args); //有自己指定的構(gòu)造器: 構(gòu)造器方式的自動注入
		}

		// 使用默認(rèn)的自己設(shè)置的高優(yōu)先級的 構(gòu)造器 Preferred constructors for default construction? // 拿到構(gòu)造器
		ctors = mbd.getPreferredConstructors();
		if (ctors != null) {
			return autowireConstructor(beanName, mbd, ctors, null);
		}
		// 默認(rèn)使用無參構(gòu)造器
		// No special handling: simply use no-arg constructor. 無需特殊處理:使用簡單的無參構(gòu)造器
		return instantiateBean(beanName, mbd);
}

工廠方法創(chuàng)建對象

方法一

如果沒有設(shè)置Supplier,則檢查BeanDefinition中是否設(shè)置了factoryMethod,也就是工廠方法,有兩種方式可以設(shè)置factoryMethod,比如:

<bean id="userService" class="cn.baldhead.service.UserService" factory-method="createUserService" />

對應(yīng)的UserService 代碼

public class UserService {

	public static UserService createUserService() {
		System.out.println("執(zhí)行createUserService()");
		UserService userService = new UserService();
		return userService;
	}

	public void test() {
		System.out.println("test");
	}

}

方法二

<bean id="commonService" class="cn.baldhead.service.CommonService"/>
<bean id="userService1" factory-bean="commonService" factory-method="createUserService" />

Spring發(fā)現(xiàn)當(dāng)前BeanDefinition方法設(shè)置了工廠方法后,就會區(qū)分這兩種方式,然后調(diào)用工廠方法得到對象。

值得注意的是,我們通過@Bean所定義的BeanDefinition,是存在factoryMethod和factoryBean的,也就是和上面的方式二非常類似,@Bean所注解的方法就是factoryMethod,AppConfig對象就是factoryBean。如果@Bean所所注解的方法是static的,那么對應(yīng)的就是方式一。

推斷構(gòu)造方法

推斷完構(gòu)造方法后,就會使用構(gòu)造方法來進(jìn)行實(shí)例化了。

額外的,在推斷構(gòu)造方法邏輯中除開會去選擇構(gòu)造方法以及查找入?yún)ο笠馔?,會還判斷是否在對應(yīng)的類中是否存在使用@Lookup注解了方法。如果存在則把該方法封裝為LookupOverride對象并添加到BeanDefinition中。

@Lookup注解就是方法注入,例如demo如下:

@Component
public class UserService {

	private OrderService orderService;

	public void test() {
		OrderService orderService = createOrderService();
		System.out.println(orderService);
	}

	@Lookup("orderService")
	public OrderService createOrderService() {
		return null;
	}

}

在實(shí)例化時,如果判斷出來當(dāng)前BeanDefinition中沒有LookupOverride,那就直接用構(gòu)造方法反射得到一個實(shí)例對象。如果存在LookupOverride對象,也就是類中存在@Lookup注解了的方法,那就會生成一個代理對象。

BeanDefionition 的后置處理

Bean對象實(shí)例化出來之后,接下來就應(yīng)該給對象的屬性賦值了。在真正給屬性賦值之前,Spring又提供了一個擴(kuò)展點(diǎn)MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition(),可以對此時的BeanDefinition進(jìn)行加工,比如:

@Component
public class BaldHeadMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {

	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        // 可以手動給 beanDefinition 得ptopertyValues 添加一個屬性賦值,屬性名-值(bean中的屬性賦值)
		if ("baldHeadService".equals(beanName)) {
			beanDefinition.getPropertyValues().add("orderService", new OrderService());
		}
	}
}

源碼在--doCreateBean()

/ Allow post-processors to modify the merged bean definition.
		// 允許(MergedBeanDefinitionPostProcessor)增強(qiáng)器修改合并的bean definition 修改BD信息
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

在Spring源碼中,AutowiredAnnotationBeanPostProcessor就是一個MergedBeanDefinitionPostProcessor,它的postProcessMergedBeanDefinition()中會去查找注入點(diǎn),并緩存在AutowiredAnnotationBeanPostProcessor對象的一個Map中(injectionMetadataCache)。

實(shí)例化后

AbstractAutowireCapableBeanFactory.poputlateBean()

// 設(shè)置屬性注入   之前bean的狀態(tài),例如,屬性賦值之前后置處理器可以提前處理些東西
// 支持字段注入  (但是在此處什么事都沒做)
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
   for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
      if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
         return;
      }
   }
}

屬性填充

AbstractAutowireCapableBeanFactory.populateBean()

spring的注入

? 必須要有對應(yīng)屬性的set方法,type:根據(jù)參數(shù)的類型去找到對應(yīng)的Bean,name:根據(jù)方法setxxx后面的一串去找到對應(yīng)的 Bean ,例如當(dāng)前就是用的 xxx 作為name去找

只要是set 方法 Spring 都會去調(diào)用,不管這個set方法是做什么的,都會去調(diào)用

? BY_TYPE,BY_NAME

	// 獲取所有屬性的值
		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable. 通過名稱自動注入?yún)?shù)的值
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable. 通過類型注入?yún)?shù)的值
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}

自動注入

處理屬性

這個步驟中,就會處理@Autowired、@Resource、@Value等注解,也是通過InstantiationAwareBeanPostProcessor.postProcessProperties()擴(kuò)展點(diǎn)來實(shí)現(xiàn)的,比如我們甚至可以實(shí)現(xiàn)一個自己的自動注入功能,比如:

@Component
public class BaldHeadInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

	@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
		if ("baldHeadService".equals(beanName)) {
			for (Field field : bean.getClass().getFields()) {
				if (field.isAnnotationPresent(BaldHeadInject.class)) {
					field.setAccessible(true);
					try {
						field.set(bean, "123");
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					}
				}
			}
		}

		return pvs;
	}
}

Aware回調(diào)

AbstractAutowireCapableBeanFactory.initializeBean(..);

回調(diào)執(zhí)行Aware接口

完成了屬性賦值之后,Spring會執(zhí)行一些回調(diào),包括:

  • BeanNameAware:回傳beanName給bean對象。
  • BeanClassLoaderAware:回傳classLoader給bean對象。
  • BeanFactoryAware:回傳beanFactory給對象。

初始化前

初始化前,也是Spring提供的一個擴(kuò)展點(diǎn):BeanPostProcessor.postProcessBeforeInitialization(),比如

@Component
public class BaldHeadBeanPostProcessor implements BeanPostProcessor {

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if ("baldHeadService".equals(beanName)) {
			System.out.println("初始化前");
		}

		return bean;
	}
}

利用初始化前,可以對進(jìn)行了依賴注入的Bean進(jìn)行處理。

在Spring源碼中:

1.InitDestroyAnnotationBeanPostProcessor會在初始化前這個步驟中執(zhí)行@PostConstruct的方法,

2.ApplicationContextAwareProcessor會在初始化前這個步驟中進(jìn)行其他Aware的回調(diào):

  • EnvironmentAware:回傳環(huán)境變量
  • EmbeddedValueResolverAware:回傳占位符解析器
  • ResourceLoaderAware:回傳資源加載器
  • ApplicationEventPublisherAware:回傳事件發(fā)布器
  • MessageSourceAware:回傳國際化資源
  • ApplicationStartupAware:回傳應(yīng)用其他監(jiān)聽對象,可忽略
  • ApplicationContextAware:回傳Spring容器ApplicationContext

4.@PostConstruct @PreDestory 也是在初始化前這一步進(jìn)行的解析,并做了一個緩存

5.InitDestroyAnnotationBeanPostProcessor.buildLifecycleMetadata()

	private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
		if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
			return this.emptyLifecycleMetadata;
		}

        // 這里面就會有 @PostConstruct 的,并且初始化方法有先后執(zhí)行順序,父類的排在前面,子類的在后面
        // 父類優(yōu)先執(zhí)行
		List<LifecycleElement> initMethods = new ArrayList<>();
        // 這里面會有 @PreDestroy 的
		List<LifecycleElement> destroyMethods = new ArrayList<>();
		Class<?> targetClass = clazz;

		do {
			final List<LifecycleElement> currInitMethods = new ArrayList<>();
			final List<LifecycleElement> currDestroyMethods = new ArrayList<>();

			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
				if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
					LifecycleElement element = new LifecycleElement(method);
					currInitMethods.add(element);
					if (logger.isTraceEnabled()) {
						logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
					}
				}
				if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
					currDestroyMethods.add(new LifecycleElement(method));
					if (logger.isTraceEnabled()) {
						logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
					}
				}
			});
			// 父類的初始化方法在前,也就是有一個先后順序,先執(zhí)行父類的 init-method 方法
			initMethods.addAll(0, currInitMethods);
			destroyMethods.addAll(currDestroyMethods);
			targetClass = targetClass.getSuperclass();
		}
		while (targetClass != null && targetClass != Object.class);

		return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
				new LifecycleMetadata(clazz, initMethods, destroyMethods));
	}

初始化

查看當(dāng)前Bean對象是否實(shí)現(xiàn)了InitializingBean接口,如果實(shí)現(xiàn)了就調(diào)用其afterPropertiesSet()方法

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {
		// 檢查是否實(shí)現(xiàn)了 InitializingBean 接口
		boolean isInitializingBean = (bean instanceof InitializingBean);
		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
			if (logger.isTraceEnabled()) {
				logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
			}
			// 實(shí)現(xiàn)了 InitializingBean 接口,執(zhí)行調(diào)用 afterPropertiesSet 方法
			// 使用了多態(tài)的操作方式 將 bean 轉(zhuǎn)換為一個接口(initializingBean)
			((InitializingBean) bean).afterPropertiesSet();
		}

		if (mbd != null && bean.getClass() != NullBean.class) {
			// 獲取自定一個init-method方法
			String initMethodName = mbd.getInitMethodName();
			if (StringUtils.hasLength(initMethodName) &&
					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) {
				// 執(zhí)行自定一個init-method方法,通過反射 method.invoke()
				invokeCustomInitMethod(beanName, bean, mbd);
			}
		}
	}

執(zhí)行BeanDefinition中指定的初始化方法

mbd.getInitMethodName()

初始化后

spring在初始化后也提供了一個擴(kuò)展點(diǎn),BeanPostProcessor.postProcessAfterInitialization()->例如:

@Component
public class BaldHeadBeanPostProcessor implements BeanPostProcessor {

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if ("baldHeadService".equals(beanName)) {
			System.out.println("初始化后");
		}

		return bean;
	}
}
if (mbd == null || !mbd.isSynthetic()) { // 初始化后執(zhí)行,postProcessor
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

可以在這個步驟中,對Bean最終進(jìn)行處理,Spring中的AOP就是基于初始化后實(shí)現(xiàn)的,初始化后返回的對象才是最終的Bean對象。

總結(jié)BeanPostProcessor

  • InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
  • 實(shí)例化
  • MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()
  • InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
  • 自動注入
  • InstantiationAwareBeanPostProcessor.postProcessProperties()
  • Aware對象
  • BeanPostProcessor.postProcessBeforeInitialization()
  • 初始化
  • BeanPostProcessor.postProcessAfterInitialization()

以上就是淺談一下Spring中的createBean 的詳細(xì)內(nèi)容,更多關(guān)于Spring createBean 的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java基于Apache FTP點(diǎn)斷續(xù)傳的文件上傳和下載

    java基于Apache FTP點(diǎn)斷續(xù)傳的文件上傳和下載

    本篇文章主要介紹了java基于Apache FTP點(diǎn)斷續(xù)傳的文件上傳和下載,利用FTP實(shí)現(xiàn)文件的上傳和下載,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2016-11-11
  • Java流形式返回前端的實(shí)現(xiàn)示例

    Java流形式返回前端的實(shí)現(xiàn)示例

    ? Java后端開發(fā)項(xiàng)目時,需要給前端傳一些數(shù)據(jù),本文主要介紹了Java流形式返回前端的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Java中的阻塞隊(duì)列詳細(xì)介紹

    Java中的阻塞隊(duì)列詳細(xì)介紹

    這篇文章主要介紹了Java中的阻塞隊(duì)列詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下
    2016-11-11
  • IDEA生成servlet程序的實(shí)現(xiàn)步驟

    IDEA生成servlet程序的實(shí)現(xiàn)步驟

    這篇文章主要介紹了IDEA生成servlet程序的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • 分布式之全面了解Kafka的使用與特性

    分布式之全面了解Kafka的使用與特性

    Kafka?是我工作多年使用最多的消息中間件?,特點(diǎn)是擁有巨大吞吐量(數(shù)百萬/秒),作為當(dāng)下最流行的分布式,可水平擴(kuò)展,可容錯的“消息系統(tǒng)”,下面跟隨小編看下分布式之全面了解Kafka的使用與特性
    2021-11-11
  • JVM加載一個類的過程

    JVM加載一個類的過程

    本文主要介紹了JVM加載一個類的過程。具有很好的參考價值,下面跟著小編一起來看下吧
    2017-02-02
  • 不寫mybatis的@Param有的報錯有的卻不報錯問題分析

    不寫mybatis的@Param有的報錯有的卻不報錯問題分析

    這篇文章主要為大家介紹了不寫mybatis的@Param有的報錯有的卻不報錯問題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • java使用TimeZone將中國標(biāo)準(zhǔn)時間轉(zhuǎn)成時區(qū)值

    java使用TimeZone將中國標(biāo)準(zhǔn)時間轉(zhuǎn)成時區(qū)值

    這篇文章主要介紹了java使用TimeZone將中國標(biāo)準(zhǔn)時間轉(zhuǎn)成時區(qū)值的相關(guān)資料,需要的朋友可以參考下
    2023-11-11
  • springboot使用redis實(shí)現(xiàn)從配置到實(shí)戰(zhàn)

    springboot使用redis實(shí)現(xiàn)從配置到實(shí)戰(zhàn)

    本文主要介紹了springboot使用redis ,采用的是RedisTemplate的形式,還有一種采用spring支持的注解進(jìn)行訪問緩存,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • 解決異常處理問題:getReader()?has?already?been?called?for?this

    解決異常處理問題:getReader()?has?already?been?called?for?this

    這篇文章主要介紹了解決異常處理:getReader()?has?already?been?called?for?this問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01

最新評論