spring源码学习(七)Bean的加载(下)
来源:互联网 发布:java中super是什么意思 编辑:程序博客网 时间:2024/05/21 10:41
在加载bean的过程中,会遇到循环依赖的问题。
什么是循环依赖,spring又是怎么解决的呢?
循环依赖是指类A中有类B的字段,B类中又有类A的字段。
A-》B , B-》A
这样会造成加载A的时候要先去加载B,去加载B的时候发现A还没有加载,然后又去加载A,无限循环。
然后spring在单例模式的使用setter注入的循环依赖可以解决,通过一个提前暴露一个正在创建的bean,但是原型模式或者通过构造器注入和prototype的方式的循环依赖无法解决。
doCreateBean方法是spring创建常规Bean的方法
/** * Actually create the specified bean. Pre-creation processing has already happened * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks. * <p>Differentiates between default bean instantiation, use of a * factory method, and autowiring a constructor. * @param beanName the name of the bean * @param mbd the merged bean definition for the bean * @param args explicit arguments to use for constructor or factory method invocation * @return a new instance of the bean * @throws BeanCreationException if the bean could not be created * @see #instantiateBean * @see #instantiateUsingFactoryMethod * @see #autowireConstructor */ protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { //根据指定bean使用对应的策略来创建实例,比如:工厂方法、构造函数注入、简单初始化 instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // Allow post-processors to modify the merged bean definition. 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; } } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. //是否要提前暴露,是否循环依赖 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } //为了避免循环依赖,在bean初始化完成前就将创建的实例的objectFactory加入工厂 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; try { //对bean进行填充,将各个属性值注入,其中可能会有依赖其他bean的属性,则递归调用。 populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); } 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); } } if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); //earlySingletonReference只有在检测到循环依赖的情况下载会不为null if (earlySingletonReference != null) { //如果方法没有被改变,即被增强 if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); for (String dependentBean : dependentBeans) { //检查依赖 if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } //bean创建后,它所依赖的bean一定是已经创建的 //actualDependentBeans不为空则表示当前bean创建后其依赖的bean却没有没全部创建完,存在循环依赖 if (!actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); } } } } // Register bean as disposable. try { //根据scope来注册bean registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }
1.如果是单例则先清除缓存。
2.实例化bean,将BeanDefinition转换为BeanWrapper
转换过程异常复杂,若存在工厂方法则使用工厂方法进行初始化。
一个类有多个构造函数,每个函数参数不一样则根据参数锁定构造方法。
如果不存在工厂方法也不存在构造方法,则使用默认构造器来实例化
3.MergedBeanDefinitionPostProcessor的使用
对bean的合并后处理,Autowired注解通过此方法实现解析。
4.依赖处理
当出现循环依赖时,类会去缓存中的ObjectFactory来填充实例,这样就能解决循环依赖问题了。
5.属性填充
6.循环依赖检查
7.注册DisposabelBean
8完成创建并返回
下面是真正开始bean实例化的方法
/** * Create a new instance for the specified bean, using an appropriate instantiation strategy: * factory method, constructor autowiring, or simple instantiation. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @param args explicit arguments to use for constructor or factory method invocation * @return a BeanWrapper for the new instance * @see #obtainFromSupplier * @see #instantiateUsingFactoryMethod * @see #autowireConstructor * @see #instantiateBean */ protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // Make sure bean class is actually resolved at this point. //解析class 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) { return obtainFromSupplier(instanceSupplier, beanName); } //若工厂不为空,则用工厂方法来初始化 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); } } // Need to determine the constructor... //需要根据参数来确定构造器 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { //构造函数注入 return autowireConstructor(beanName, mbd, ctors, args); } // No special handling: simply use no-arg constructor. //默认构造函数注入 return instantiateBean(beanName, mbd); }
/** * "autowire constructor" (with constructor arguments by type) behavior. * Also applied if explicit constructor argument values are specified, * matching all remaining arguments with beans from the bean factory. * <p>This corresponds to constructor injection: In this mode, a Spring * bean factory is able to host components that expect constructor-based * dependency resolution. * @param beanName the name of the bean * @param mbd the merged bean definition for the bean * @param chosenCtors chosen candidate constructors (or {@code null} if none) * @param explicitArgs argument values passed in programmatically via the getBean method, * or {@code null} if none (-> use constructor argument values from bean definition) * @return a BeanWrapper for the new instance */ public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd, @Nullable Constructor<?>[] chosenCtors, @Nullable final Object[] explicitArgs) { BeanWrapperImpl bw = new BeanWrapperImpl(); this.beanFactory.initBeanWrapper(bw); Constructor<?> constructorToUse = null; ArgumentsHolder argsHolderToUse = null; Object[] argsToUse = null; //explicitArgs通过getBean方法传入 //如果getBean方法调用的时候指定方法参数那么直接使用 if (explicitArgs != null) { argsToUse = explicitArgs; } else { //如果在getBean方法时候没有指定则尝试从配置文件中解析 Object[] argsToResolve = null; //尝试从缓存中获取 synchronized (mbd.constructorArgumentLock) { constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod; if (constructorToUse != null && mbd.constructorArgumentsResolved) { // Found a cached constructor... //从换缓存种获取一个构造函数 argsToUse = mbd.resolvedConstructorArguments; if (argsToUse == null) { //配置的构造函数参数 argsToResolve = mbd.preparedConstructorArguments; } } } //如果缓存中存在 if (argsToResolve != null) { //解析参数类型,如给定方法的构造函数A(int,int)则通过此方法后会把配置中的字符串类型改变成其他类型 //缓存中的值可能是原始值也可能是最终值 argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve); } } //没有被缓存 if (constructorToUse == null) { // Need to resolve the constructor. boolean autowiring = (chosenCtors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR); ConstructorArgumentValues resolvedValues = null; int minNrOfArgs; if (explicitArgs != null) { minNrOfArgs = explicitArgs.length; } else { //提取配置文件中配置的构造函数参数 ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues(); //用来承载解析后的构造函数参数的值 resolvedValues = new ConstructorArgumentValues(); //能解析到的参数个数 minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues); } // Take specified constructors, if any. Constructor<?>[] candidates = chosenCtors; if (candidates == null) { Class<?> beanClass = mbd.getBeanClass(); try { candidates = (mbd.isNonPublicAccessAllowed() ? beanClass.getDeclaredConstructors() : beanClass.getConstructors()); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Resolution of declared constructors on bean Class [" + beanClass.getName() + "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex); } } //排定给定的构造函数,public构造函数优先参数数量降序、非public构造函数数量降序 AutowireUtils.sortConstructors(candidates); int minTypeDiffWeight = Integer.MAX_VALUE; Set<Constructor<?>> ambiguousConstructors = null; LinkedList<UnsatisfiedDependencyException> causes = null; for (Constructor<?> candidate : candidates) { Class<?>[] paramTypes = candidate.getParameterTypes(); if (constructorToUse != null && argsToUse.length > paramTypes.length) { // Already found greedy constructor that can be satisfied -> // do not look any further, there are only less greedy constructors left. //如果已经找到了选用的构造函数,或者需要的参数个数小于当前构造函数的参数个数则终止 break; } if (paramTypes.length < minNrOfArgs) { //参数个数不相等 continue; } ArgumentsHolder argsHolder; if (resolvedValues != null) { //有参数则根据值来构造对应参数类型参数 try { String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length); if (paramNames == null) { //获取参数名称探索器 ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer(); if (pnd != null) { //获取指定构造函数的参数名称 paramNames = pnd.getParameterNames(candidate); } } //根据名称和数据类型创造参数持有者 argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames, getUserDeclaredConstructor(candidate), autowiring); } catch (UnsatisfiedDependencyException ex) { if (this.beanFactory.logger.isTraceEnabled()) { this.beanFactory.logger.trace( "Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex); } // Swallow and try next constructor. if (causes == null) { causes = new LinkedList<>(); } causes.add(ex); continue; } } else { // Explicit arguments given -> arguments length must match exactly. if (paramTypes.length != explicitArgs.length) { continue; } //构造函数没有参数的情况 argsHolder = new ArgumentsHolder(explicitArgs); } //探测是否有不确定性的构造器存在,比如不同构造器的参数为父子关系 int typeDiffWeight = (mbd.isLenientConstructorResolution() ? argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes)); // Choose this constructor if it represents the closest match. //如果它代表着当前最接近的匹配则选择作为构造函数 if (typeDiffWeight < minTypeDiffWeight) { constructorToUse = candidate; argsHolderToUse = argsHolder; argsToUse = argsHolder.arguments; minTypeDiffWeight = typeDiffWeight; ambiguousConstructors = null; } else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) { if (ambiguousConstructors == null) { ambiguousConstructors = new LinkedHashSet<>(); ambiguousConstructors.add(constructorToUse); } ambiguousConstructors.add(candidate); } } if (constructorToUse == null) { if (causes != null) { UnsatisfiedDependencyException ex = causes.removeLast(); for (Exception cause : causes) { this.beanFactory.onSuppressedException(cause); } throw ex; } throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Could not resolve matching constructor " + "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)"); } else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Ambiguous constructor matches found in bean '" + beanName + "' " + "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " + ambiguousConstructors); } if (explicitArgs == null) { //将解析的构造函数加入缓存 argsHolderToUse.storeCache(mbd, constructorToUse); } } try { final InstantiationStrategy strategy = beanFactory.getInstantiationStrategy(); Object beanInstance; if (System.getSecurityManager() != null) { final Constructor<?> ctorToUse = constructorToUse; final Object[] argumentsToUse = argsToUse; beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () -> strategy.instantiate(mbd, beanName, beanFactory, ctorToUse, argumentsToUse), beanFactory.getAccessControlContext()); } else { beanInstance = strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse); } //将构建的实例加入BeanWrapper中 bw.setBeanInstance(beanInstance); return bw; } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean instantiation via constructor failed", ex); } }
1.构造函数的确定
通过对explicitArgs参数判断
2.从缓存中获取
如果参数之前已经分析过,那么可以直接从缓存中获取
3.从配置文件获取
如果不能根据传入的参数explicitArgs确定构造函数的参数也无法在缓存中得到相关信息。只能从配置文件中的配置构造函数信息开始。我们知道配置文件的信息通过处理后已经被放在了BeanDefinition中了,获益可以通过getConstructorArgumentValues()来获取配置构造函数信息。
根据确定的构造函数来转换对应的参数类型
构造函数不确定性的验证。
根据实例化策略以及得到的构造函数以及构造函数参数实例化bean
/** * Instantiate the given bean using its default constructor. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @return a BeanWrapper for the new instance */ protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) { try { Object beanInstance; final BeanFactory parent = this; if (System.getSecurityManager() != null) { beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, parent), getAccessControlContext()); } else { beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); } BeanWrapper bw = new BeanWrapperImpl(beanInstance); initBeanWrapper(bw); return bw; } catch (Throwable ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); } }
@Override public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { // Don't override the class with CGLIB if no overrides. //如果有需要方法覆盖或者动态替换方法则需要用cglib //没有直接反射就行了 if (bd.getMethodOverrides().isEmpty()) { 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); } }
bd.getMethodOverrides()来判断是否有replace或者lookup配置方法,如没有就直接反射。有的话要将方法配置提供功能的切口进去,所以就要使用动态代理的方式将包含两个特性所对应的逻辑的拦截增强器设置进去,这样才可以保证方法在调用方法的时候会被相应的拦截器增强,返回值为包含拦截器的代理实例。
未完待续……
- spring源码学习(七)Bean的加载(下)
- spring源码学习(五)Bean的加载(上)
- spring源码学习(六)Bean的加载(中)
- Spring源码(五)-bean的加载(下)
- spring源码初步学习-bean的加载
- bean的加载(七)创建bean
- 《Spring源码深度解析》学习笔记——bean的加载(一)
- spring源码阅读之Bean的加载(一)
- spring源码阅读之Bean的加载(二)
- spring源码(12)加载指定bean前,先加载依赖的bean
- Spring(七):Bean的生命周期
- spring源码阅读(七)之bean解析
- Spring源码之bean的加载(一)
- Spring源码解析之Bean的加载
- Spring源码解析-bean的加载
- Spring源码(四)-bean的加载(上)
- Spring源码阅读之Bean加载(xml)1
- Spring源码阅读之Bean加载(annotation )2
- 仿微信的弹出菜单—ALActionSheetView
- 获取当前服务器ip地址
- easyui行文本编辑,日期编辑
- Chrome开发者工具面板功能
- 文件权限的操作
- spring源码学习(七)Bean的加载(下)
- Git:warning: ignoring broken ref refs/remotes/origin/HEAD
- 4Qt音乐播放器的设计
- Selenium学习三——利用Python爬取网页表格数据并存到excel
- Windows 关闭某个进程
- Linux虚拟机中安装系统
- 基本的用户管理
- average variance standardDeviation
- 手写连接池