您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“Spring Bean怎么初始化”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“Spring Bean怎么初始化”這篇文章吧。
做Java都有很多年了,一直有一個疑惑: Spring 如何初始化bean,怎么調用反射實例化對象的,自己動手來解除這個疑惑。 過去我認為spring bean對象實例化一直都是由BeanPostProcessor接口實現類去做的,我就是不知道具體那個實現類。
為什么面試官特別喜歡問創建bean的三級緩存,主要是因為bean創建都是伴隨著三級緩存之間的轉換完成的,對象不同狀態分別存在不同緩存中,下面我會在分析代碼時,順便支持對象如何在緩存中流轉的。 先了解下spring 三級緩存。
/** 一級緩存 用于存放完全可以使用單例bean,也就是初始化完成并且注入所有依賴 */ private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); /** 二級緩存 過早暴露單例對象,此時bean剛剛完成初始化,未完成屬性注入和執行 init 方法 */ private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16); /** 三級緩存 裝載創建bean的工廠對象 */ private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16)
三級緩存主要作用: 創建對象ObjectFactory首先放入三級換緩存中,當調用getObject 創建實例時,會將創建好對象加入二級緩存中,并且刪除三級中緩存,當對象已經完成初始化方法和屬性注入,再將緩存添加到一級緩存中,并且刪除二級緩存。
從源頭開始找,所有spring bean 初始化都是由AbstractBeanFactory.doGetBean
方法實現的。下面我將源碼減除臃腫部分,貼出來。
protected <T> T doGetBean( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { //name 前綴處理 beanFactory beanName 帶有&開頭 String beanName = transformedBeanName(name); Object beanInstance; //從三級緩存去取bean,三級中都沒有則返回null,說明對象還沒有創建 Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { //如果緩存中bean 是FactoryBean實例,要通過接口獲取到實際bean beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { //判斷bean對象標記是否正在創建中,如果正在創建中則不應該繼續下去,出現依賴循環就會出現這個錯誤 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } BeanFactory parentBeanFactory = getParentBeanFactory(); // 檢查父容器是否存在,嘗試從父容器中獲取 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { return (T) parentBeanFactory.getBean(nameToLookup, args); } else if (requiredType != null) { return parentBeanFactory.getBean(nameToLookup, requiredType); } else { return (T) parentBeanFactory.getBean(nameToLookup); } } if (!typeCheckOnly) { //緩存中標記beanName 正在被創建 markBeanAsCreated(beanName); } StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate") .tag("beanName", name); try { if (requiredType != null) { beanCreation.tag("beanType", requiredType::toString); } RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { //bean 中@DependsOn 信息,用于標記bean之間初始化順序,優先創建@DependsOn 中bean for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } registerDependentBean(dep, beanName); try { getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } //創建單例對象 if (mbd.isSingleton()) { //重點就在這里實例化對象 ,getSingleton 就是在這里將創建完成對象加入到一級緩存中 sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) destroySingleton(beanName); throw ex; } }); //如果生成bean 是FactoryBean ,再獲取真正的對象 beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } //作用域 = prototype,因為不會放入緩存中,每次獲取都要重新創建 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); } beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { // session request 這些作用域,由作用域容器去管理這些對象 String scopeName = mbd.getScope(); if (!StringUtils.hasLength(scopeName)) { throw new IllegalStateException("No scope name defined for bean ′" + beanName + "'"); } 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, () -> { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } }); beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new ScopeNotActiveException(beanName, scopeName, ex); } } } catch (BeansException ex) { beanCreation.tag("exception", ex.getClass().toString()); beanCreation.tag("message", String.valueOf(ex.getMessage())); cleanupAfterBeanCreationFailure(beanName); throw ex; } finally { beanCreation.end(); } } //返回初始化成功的對象,一個對象初始化就這樣完成的了 return adaptBeanInstance(name, beanInstance, requiredType); }
大概總結一下上面代碼流程:
先從三級緩存中獲取,如果緩存中都沒有。再去判斷是否存在父容器,從父容器中獲取。沒有正式進入bean 初始化流程,先根據beanName 獲取到RootBeanDefinition,bean類元信息、先處理dependsOn中bean,保證bean依賴的創建順序,下面會說明org.springframework.context.annotation.@DependsOn
這個注解。下一步按照不同scope 進行bean 對象初始化。初始化流程就是這樣,我們將目光放在單例bean 如何實例化,集中關注AbstractAutowireCapableBeanFactory.createBean
獲取注冊一個單例對象
@DependsOn
注解意思是實例化某個對象依賴于某一個實例化,但是不需要持有這個實例對象。比如bean A上 需要依賴bean b才能實例化,但是bean b 不需要作為他的屬性,常常用于不同實例實例化順序標記。
看下getSingleton方法
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { synchronized (this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { if (this.singletonsCurrentlyInDestruction) { //標記bean 是否在銷毀 throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); } beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { } catch (BeanCreationException ex) { throw ex; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } afterSingletonCreation(beanName); } if (newSingleton) { addSingleton(beanName, singletonObject); //就是在這里刪除二三級緩存,提交到一級緩存 } } return singletonObject; } } protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } }
添加到一級緩存則說明bean已經完成實例化,可以正常使用了。下面看下如何進行實例化和屬性注入的。
下面進入AbstractAutowireCapableBeanFactory.createBean
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { RootBeanDefinition mbdToUse = mbd; //克隆一份mbd => mbdToUse Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // Prepare method overrides. try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. //通過BeanPostProcessors 增強返回一個代理對象,這個生成AOP的代理對象,使用多個BeanPostProcessors來處理 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } try { // bean 對象實例化就這里實現 Object beanInstance = doCreateBean(beanName, mbdToUse, args); return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); } }
這里邏輯就比較簡單了 ,克隆一份RootBeanDefinition用于初始化對象,resolveBeforeInstantiation 主要用于初始化代理對象情況,主要使用BeanPostProcessor子類InstantiationAwareBeanPostProcessor實現方法去實現對象初始化,并且在實例化成功后在調用后置方法進行對象依賴注入,這里可以看見此方法返回對象直接跳出方法棧,這里可以看出單例和代理對象還是有區別的。單例對象初始化就在doCreateBean 實現了
下面就是AbstractAutowireCapableBeanFactory.doCreateBean
非常接近對象如何實例化的了
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); //這個就是實例化方法 } Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // 使用BeanDefinitionPostProcessors 對合并bean進行實例化 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; } } // 這里就需要用到上面說的三級緩存知識了 // even when triggered by lifecycle interfaces like BeanFactoryAware. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); //是否放入第三級緩存中 if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); //將已經實例化的對象加入到第三級緩存 singletonFactories } // Initialize the bean instance. Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); //對屬性進入注入,下面會具體分析的 exposedObject = initializeBean(beanName, exposedObject, mbd); //執行初始化方法,或者注入Aware 接口bean } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } //下面代碼省略 //主要就是對設置了DisposableBean 接口銷毀鉤子方法處理 }
這里代碼主要分成三部分
初始化實例,創建對象完成,并且添加到3級緩存。第3級緩存常常用于存儲代理對象,因為有些類需要動態代理方法,需要生成代理對象,會委派給第三級緩存方法ObjectFactroy去實現的,普通對象如果不需要會直接返回。
對實例化bean進行屬性注入
執行初始化方法,DisposableBean接口加入到disposableBeans容器中
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // 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()); } Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); if (instanceSupplier != null) {// 有實現Supplier 接口,由instanceSupplier.get() 方法創建實例 return obtainFromSupplier(instanceSupplier, beanName); } //factoryName 使用工廠模式創建bean,調用工廠方法去創建,這個支持靜態方法和factoryBean.invoke 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); } } // 獲取構造函數參數 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); } // Preferred constructors for default construction? ctors = mbd.getPreferredConstructors(); if (ctors != null) { return autowireConstructor(beanName, mbd, ctors, null); } // No special handling: simply use no-arg constructor. return instantiateBean(beanName, mbd); }
實例化方法instantiateBean最終會調用SimpleInstantiationStrategy.instantiate 進行實例化
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { // Don't override the class with CGLIB if no overrides. if (!bd.hasMethodOverrides()) { Constructor<?> constructorToUse; synchronized (bd.constructorArgumentLock) { constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod; if (constructorToUse == null) { final Class<?> clazz = bd.getBeanClass(); if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { if (System.getSecurityManager() != null) { constructorToUse = AccessController.doPrivileged( (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor); } else { constructorToUse = clazz.getDeclaredConstructor(); //獲取構造函數 } bd.resolvedConstructorOrFactoryMethod = constructorToUse; } catch (Throwable ex) { throw new BeanInstantiationException(clazz, "No default constructor found", ex); } } } return BeanUtils.instantiateClass(constructorToUse); //調用構造函數進行實例化 } else { // Must generate CGLIB subclass. return instantiateWithMethodInjection(bd, beanName, owner); } }
@Override public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { // Don't override the class with CGLIB if no overrides. if (!bd.hasMethodOverrides()) { Constructor<?> constructorToUse; synchronized (bd.constructorArgumentLock) { constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod; if (constructorToUse == null) { final Class<?> clazz = bd.getBeanClass(); if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface"); } try { if (System.getSecurityManager() != null) { constructorToUse = AccessController.doPrivileged( (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor); } else { constructorToUse = clazz.getDeclaredConstructor(); } bd.resolvedConstructorOrFactoryMethod = constructorToUse; } catch (Throwable ex) { throw new BeanInstantiationException(clazz, "No default constructor found", ex); } } } return BeanUtils.instantiateClass(constructorToUse); //調用構造器進行初始化 } else { // Must generate CGLIB subclass. return instantiateWithMethodInjection(bd, beanName, owner); } }
這里要注意下先判斷bean是否有方法重寫的,沒有則使用反射生成的構造器,有就使用gclib方式創建代理對象,具體實現方式就在org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate
,有興趣同學可以去學習下。 到此一個簡單bean實例化完成了。
下面進入IOC另一個特點,bean注入,先從AbstractAutowireCapableBeanFactory.populateBean
方法開始
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. //通過InstantiationAwareBeanPostProcessors.postProcessAfterInstantiation 如果返回true,目標實例內部的返回值會被populate,否則populate這個過程會被忽視 //翻譯說如果返回true可以執行字段注入 真的6666啊 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) { if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); //獲取注入方式分布有4種 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. if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); //依賴方式,模式都是沒有類型檢查,這種依賴方式一般都是xml 配置用得比較多,沒有配置這里都是返回false boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); / PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) { PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); //獲取注解標注需要注入方法或者是字段,并且進行注入 if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); } if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } }
小知識點: AutowireCapableBeanFactory.AUTOWIRE_NO 表明不會對當前Bean進行外部類的注入,常規使用@Autowire、@Resource 都是這類型 剩下三種都是通過xml 或者 AutowireCapableBeanFactory.autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) 進行設置autowireMode 。
根據上面代碼可以知道主流程bean注入都是由InstantiationAwareBeanPostProcessor 進行處理的,簡單說明接口方法
方法 | 描述 |
---|---|
postProcessBeforeInitialization | 方法是最 先執行的方法,它在目標對象實例化之前調用,該方法的返回值類型是Object,我們可以返回任何類型的值。由于這個時候目標對象還未實例化,所以這個返回值可以用來代替原本該生成的目標對象的實例(比如代理對象)。如果該方法的返回值代替原本該生成的目標對象,后續只有postProcessAfterInitialization方法會調用,其它方法不再調用;否則按照正常的流程走 |
postProcessAfterInitialization | 方法在目標對象實例化之后調用,這個時候對象已經被實例化,但是該實例的屬性還未被設置,都是null。因為它的返回值是決定要不要調用postProcessPropertyValues方法的其中一個因素(因為還有一個因素是mbd.getDependencyCheck());如果該方法返回false,并且不需要check,那么postProcessPropertyValues就會被忽略不執行;如果返回true,postProcessPropertyValues就會被執行 |
postProcessPropertyValues | 對bean屬性值賦值后調用,對屬性值的修改。如果postProcessAfterInstantiation方法返回false,該方法可能不會被調用。可以在該方法內對屬性值進行修改 |
postProcessProperties | Bean屬性賦值就是調用這個方法的 |
InstantiationAwareBeanPostProcessor 接口實現類主要分3個
ConfigurationClassPostProcessor:看類名就知道處理@Configuration實例化,并沒有屬性注入邏輯,不詳講略過。
CommonAnnotationBeanPostProcessor:這個類就是實現bean注入,但是是實現JSR-250 注解、@Resource,@EJB、@WebServiceRef,@WebServiceContext,@PostConstrusct、@PreDestory這些注解實現。
AutowiredAnnotationBeanPostProcessor:實現 @Autowired、@Value注入,并且支持JSR-330's @Inject,主要分析這個類就可以知道bean 注入的。
private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4); @SuppressWarnings("unchecked") public AutowiredAnnotationBeanPostProcessor() { this.autowiredAnnotationTypes.add(Autowired.class); this.autowiredAnnotationTypes.add(Value.class); try { this.autowiredAnnotationTypes.add((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader())); logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring"); } catch (ClassNotFoundException ex) { // JSR-330 API not available - simply skip. } }
在初始化時就將支持注解加入集合中,再使用掃描器去掃描方法、構造器、字段,如果有這些注解就進行注入。
看下怎么判斷是否需要注入的
@Nullable private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) { MergedAnnotations annotations = MergedAnnotations.from(ao); for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) { MergedAnnotation<?> annotation = annotations.get(type); if (annotation.isPresent()) { return annotation; } } return null; }
AccessibleObject 是Method、Field、Constructor 父類。
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { //獲取需要注入字段,方法 InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); try { metadata.inject(bean, beanName, pvs); //注入 } catch (BeanCreationException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex); } return pvs; } //下面就行獲取InjectionMetadata private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) { // Fall back to class name as cache key, for backwards compatibility with custom callers. String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); // 快速從緩存中獲取,如果沒有加鎖去解析,然后在結果放入緩存中 InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); if (InjectionMetadata.needsRefresh(metadata, clazz)) { synchronized (this.injectionMetadataCache) { //雙重檢查 metadata = this.injectionMetadataCache.get(cacheKey); if (InjectionMetadata.needsRefresh(metadata, clazz)) { if (metadata != null) { metadata.clear(pvs); } metadata = buildAutowiringMetadata(clazz); this.injectionMetadataCache.put(cacheKey, metadata); } } } return metadata; }
InjectionMetadata 主要是集合bean需要被注入類型,因為已經解析過bean Class信息了,相當于解析結果裝起來
看下如何去掃描方法、字段的
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) { //從給定注解中判斷class 是否攜帶這個注解 if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) { return InjectionMetadata.EMPTY; } List<InjectionMetadata.InjectedElement> elements = new ArrayList<>(); Class<?> targetClass = clazz; do { final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>(); //遍歷所有Field,找出掃描的注解,特意標注不支持static 修飾field ReflectionUtils.doWithLocalFields(targetClass, field -> { MergedAnnotation<?> ann = findAutowiredAnnotation(field); if (ann != null) { if (Modifier.isStatic(field.getModifiers())) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation is not supported on static fields: " + field); } return; } // 獲取注解內 required 值 boolean required = determineRequiredStatus(ann); currElements.add(new AutowiredFieldElement(field, required)); } }); ReflectionUtils.doWithLocalMethods(targetClass, method -> { //獲取方法上橋接方法,因為泛型類型擦除,要對橋接方法進行安全檢查,防止在調用是出現異常 Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return; } //獲取注解 MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod); //方法安全檢查 if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { if (Modifier.isStatic(method.getModifiers())) { //不支持靜態方法注入 if (logger.isInfoEnabled()) { logger.info("Autowired annotation is not supported on static methods: " + method); } return; } if (method.getParameterCount() == 0) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation should only be used on methods with parameters: " + method); } } boolean required = determineRequiredStatus(ann); PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); currElements.add(new AutowiredMethodElement(method, required, pd)); } }); // 這樣寫是為了后面加入排在隊列前面,父類屬性優先于子類 elements.addAll(0, currElements); targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); //這里寫得很好,向上解析父類,直到是Object 為止 return InjectionMetadata.forElements(elements, clazz); }
邏輯非常簡單,就是根據給定注解去class獲取指定的注解,從而獲取到需要注入類型,但是幾行簡單的代碼可以看出強大編碼能力,學習了????。 現在需要注入對象已經獲取到,看如何注入吧
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Collection<InjectedElement> checkedElements = this.checkedElements; Collection<InjectedElement> elementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements); if (!elementsToIterate.isEmpty()) { for (InjectedElement element : elementsToIterate) { element.inject(target, beanName, pvs); } } } @Override protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Field field = (Field) this.member; Object value; if (this.cached) { try { value = resolvedCachedArgument(beanName, this.cachedFieldValue); } catch (NoSuchBeanDefinitionException ex) { // Unexpected removal of target bean for cached argument -> re-resolve value = resolveFieldValue(field, bean, beanName); } } else { value = resolveFieldValue(field, bean, beanName); } if (value != null) { ReflectionUtils.makeAccessible(field); field.set(bean, value); } } private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) { DependencyDescriptor desc = new DependencyDescriptor(field, this.required); desc.setContainingClass(bean.getClass()); Set<String> autowiredBeanNames = new LinkedHashSet<>(1); Assert.state(beanFactory != null, "No BeanFactory available"); TypeConverter typeConverter = beanFactory.getTypeConverter(); //類型轉換器 Object value; try { value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex); } synchronized (this) { if (!this.cached) { Object cachedFieldValue = null; if (value != null || this.required) { cachedFieldValue = desc; // 將注入關系添加到容器中,方便bean銷毀時同步銷毀 registerDependentBeans(beanName, autowiredBeanNames); if (autowiredBeanNames.size() == 1) { String autowiredBeanName = autowiredBeanNames.iterator().next(); if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { //這些都是為了緩存起來 cachedFieldValue = new ShortcutDependencyDescriptor( desc, autowiredBeanName, field.getType()); } } } this.cachedFieldValue = cachedFieldValue; this.cached = true; } } return value; } }
主要核心是如從緩存獲取到需要注入類型實例在beanFactory.resolveDependency
中 進入DefaultListableBeanFactory看下
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { descriptor.initParameterNameDiscovery(getParameterNameDiscoverer()); if (Optional.class == descriptor.getDependencyType()) { return createOptionalDependency(descriptor, requestingBeanName); } else if (ObjectFactory.class == descriptor.getDependencyType() || ObjectProvider.class == descriptor.getDependencyType()) { return new DependencyObjectProvider(descriptor, requestingBeanName); } else if (javaxInjectProviderClass == descriptor.getDependencyType()) { return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName); } else { //懶加載 掃描@Lazy注解,返回一個代理對象 Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary( descriptor, requestingBeanName); if (result == null) { result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); } return result; } }
@Lazy 使用注解修飾bean 或者Class,在容器初始化化時不會立刻創建,只要需要使用bean才會創建的。 根據類型Optional、ObjectFactory、Provider,還有懶加載情景不同的處理,這些處理本質都是要調用doResolveDependency方法初始化對象,無論那種對象都要 獲取原始對象然后再交給這些接口去包裝增強。
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { //如果這個注入是通過構造器注入,可以從構造器解析緩存中去獲取注入信息點 InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor); try { Object shortcut = descriptor.resolveShortcut(this); if (shortcut != null) { return shortcut; } Class<?> type = descriptor.getDependencyType(); //嘗試從注解中獲取默認值 @Value 的value Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); if (value != null) { if (value instanceof String) { String strVal = resolveEmbeddedValue((String) value); BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null); value = evaluateBeanDefinitionString(strVal, bd); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); try { return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor()); } catch (UnsupportedOperationException ex) { // A custom TypeConverter which does not support TypeDescriptor resolution... return (descriptor.getField() != null ? converter.convertIfNecessary(value, type, descriptor.getField()) : converter.convertIfNecessary(value, type, descriptor.getMethodParameter())); } } //多種混合類型處理,stream、collection、Map Array 這些 Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter); if (multipleBeans != null) { return multipleBeans; } //根據類型獲取容器中bean名,返回map key就是bean名,value 初始從容器中獲取對象,如果沒有找到就會拋出異常了 Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); if (matchingBeans.isEmpty()) { if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } return null; } String autowiredBeanName; Object instanceCandidate; if (matchingBeans.size() > 1) { //出現一個類型,不同實例,可以根據@Primary, @Priority、屬性名方式去配置 autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor); if (autowiredBeanName == null) { if (isRequired(descriptor) || !indicatesMultipleBeans(type)) { //沒有確定,拋出異常 return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans); } else { return null; } } instanceCandidate = matchingBeans.get(autowiredBeanName); } else { // We have exactly one match. Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next(); autowiredBeanName = entry.getKey(); instanceCandidate = entry.getValue(); } if (autowiredBeanNames != null) { autowiredBeanNames.add(autowiredBeanName); } if (instanceCandidate instanceof Class) { //這里其實就是從容器中獲取實例,如果這時候沒有初始化,就走上面初始化流程 instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this); } Object result = instanceCandidate; if (result instanceof NullBean) { if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } result = null; } if (!ClassUtils.isAssignableValue(type, result)) { throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass()); } return result; } finally { ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint); } }
這個方法簡單做個總結,先是處理 @Value 情況,然后通過findAutowireCandidates 通過類型去容器中獲取實例,如何實例還沒有初始化,就會調用上面那個初始化過程,將初始化對象返回。根據注入類型進行相應處理,像stream、Collection,這些混合類型都是直接添加進去。如果出現了一個類型多個bean情況,這時就是就是@Primary、@Priority這些注解來判斷或者根據屬性名去和beanName匹配,最后將bean對象返回。 這里就簡單看完一個bean初始化流程了。
以上是“Spring Bean怎么初始化”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。