【spring源码分析】IOC容器初始化(五)——查漏补缺(1)
前言:前面已经对IOC容器初始化的大致流程梳理了一遍,但是比较粗略,下面进行查漏补缺。 1.BeanDefinitionParserDelegate在对bean的xml文件进行解析的过程中BeanDefinitionParserDelegate类非常重要,这里对其进行分析。 ①checkNameUniqueness检查bean的名称是否被使用 1 /** 2 * Validate that the specified bean name and aliases have not been used already 3 * within the current level of beans element nesting. 4 */ 5 protected void checkNameUniqueness(String beanName,List<String> aliases,Element beanElement) { 6 String foundName = null; 7 8 if (StringUtils.hasText(beanName) && this.usedNames.contains(beanName)) { 9 foundName = beanName; 10 } 11 if (foundName == null) { 12 foundName = CollectionUtils.findFirstMatch(this.usedNames,aliases); 13 } 14 if (foundName != null) { 15 error("Bean name ‘" + foundName + "‘ is already used in this <beans> element",beanElement); 16 } 17 18 this.usedNames.add(beanName); 19 this.usedNames.addAll(aliases); 20 } 通过源码,可知这里对bean的name和别名都进行了检测,如果通过则会将beanName和aliases存储在usedNames中。 usedNames为HashSet,保证beanName的唯一性。 ②在解析bean元素的过程中,有如下代码,让人很费解: 通过查看ParseState源码注解,终于知道push和pop的作用: 追踪解析bean过程中的逻辑位置,如果调用#toString方法,则打印出解析bean过程中的一些相关信息。 ③decorateBeanDefinitionIfRequired方法: 1 public BeanDefinitionHolder decorateBeanDefinitionIfRequired( 2 Element ele,BeanDefinitionHolder definitionHolder,@Nullable BeanDefinition containingBd) { 3 4 System.out.println("BeanDefinitionParserDelegate#decorateBeanDefinitionIfRequired对自定义属性进行解析"); 5 BeanDefinitionHolder finalDefinition = definitionHolder; 6 7 // Decorate based on custom attributes first. 8 NamedNodeMap attributes = ele.getAttributes(); 9 for (int i = 0; i < attributes.getLength(); i++) { 10 Node node = attributes.item(i); 11 finalDefinition = decorateIfRequired(node,finalDefinition,containingBd); 12 } 13 14 // Decorate based on custom nested elements. 15 NodeList children = ele.getChildNodes(); 16 for (int i = 0; i < children.getLength(); i++) { 17 Node node = children.item(i); 18 if (node.getNodeType() == Node.ELEMENT_NODE) { 19 finalDefinition = decorateIfRequired(node,containingBd); 20 } 21 } 22 return finalDefinition; 23 } 该函数的主要作用是对bean标签的自定义属性进行解析,将解析的属性封装进BeanDefinitionHolder中(第11行),具体操作代码在decorateIfRequired函数中: 1 public BeanDefinitionHolder decorateIfRequired( 2 Node node,BeanDefinitionHolder originalDef,@Nullable BeanDefinition containingBd) { 3 4 String namespaceUri = getNamespaceURI(node); 5 if (namespaceUri != null && !isDefaultNamespace(namespaceUri)) { 6 NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); 7 if (handler != null) { 8 BeanDefinitionHolder decorated = 9 handler.decorate(node,originalDef,new ParserContext(this.readerContext,this,containingBd)); 10 if (decorated != null) { 11 return decorated; 12 } 13 } 14 else if (namespaceUri.startsWith("http://www.springframework.org/")) { 15 error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]",node); 16 } 17 else { 18 // A custom namespace,not to be handled by Spring - maybe "xml:...". 19 if (logger.isDebugEnabled()) { 20 logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]"); 21 } 22 } 23 } 24 return originalDef; 25 } 分析: 注意第5行会判断节点的空间类型,只有自定义空间类型才会进入分支,通过空间uri获得空间处理器,对于bean的属性对应的是:http://www.springframework.org/schema/p标签,会取得SimplePropertyNamespaceHandler处理器,第9行:通过decorate方法进行处理: 1 @Override 2 public BeanDefinitionHolder decorate(Node node,BeanDefinitionHolder definition,ParserContext parserContext) { 3 if (node instanceof Attr) { 4 Attr attr = (Attr) node; 5 String propertyName = parserContext.getDelegate().getLocalName(attr); 6 String propertyValue = attr.getValue(); 7 MutablePropertyValues pvs = definition.getBeanDefinition().getPropertyValues(); 8 if (pvs.contains(propertyName)) { 9 parserContext.getReaderContext().error("Property ‘" + propertyName + "‘ is already defined using " + 10 "both <property> and inline syntax. Only one approach may be used per property.",attr); 11 } 12 if (propertyName.endsWith(REF_SUFFIX)) { 13 propertyName = propertyName.substring(0,propertyName.length() - REF_SUFFIX.length()); 14 pvs.add(Conventions.attributeNameToPropertyName(propertyName),new RuntimeBeanReference(propertyValue)); 15 } 16 else { 17 pvs.add(Conventions.attributeNameToPropertyName(propertyName),propertyValue); 18 } 19 } 20 return definition; 21 } 这里就是将bean的属性以键值对的形式存入MutablePropertyValues中,key=属性名,value=属性值。 通过对bean标签属性的循环遍历,就将属性值封装到BeanDefinitionHolder中了。 总的来说BeanDefinitionParserDelegate类,主要对bean标签的相关属性进行解析。 2.DefaultListableBeanFactory在实例化bean对象时,用的是DefaultListableBeanFactory的preInstantiateSingletons方法: 1 public void preInstantiateSingletons() throws BeansException { 2 if (this.logger.isDebugEnabled()) { 3 this.logger.debug("Pre-instantiating singletons in " + this); 4 } 5 6 // Iterate over a copy to allow for init methods which in turn register new bean definitions. 7 // While this may not be part of the regular factory bootstrap,it does otherwise work fine. 8 List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); 9 10 // Trigger initialization of all non-lazy singleton beans... 11 for (String beanName : beanNames) { 12 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); 13 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { 14 if (isFactoryBean(beanName)) { 15 Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); 16 if (bean instanceof FactoryBean) { 17 final FactoryBean<?> factory = (FactoryBean<?>) bean; 18 boolean isEagerInit; 19 if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { 20 isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) 21 ((SmartFactoryBean<?>) factory)::isEagerInit,22 getAccessControlContext()); 23 } 24 else { 25 isEagerInit = (factory instanceof SmartFactoryBean && 26 ((SmartFactoryBean<?>) factory).isEagerInit()); 27 } 28 if (isEagerInit) { 29 getBean(beanName); 30 } 31 } 32 } 33 else { 34 System.out.println("在DefaultListableBeanFactory#preInstantiateSingletons中实现bean的初始化,会调用AbstractBeanFactory的getBean方法"); 35 getBean(beanName); 36 } 37 } 38 } 39 40 // Trigger post-initialization callback for all applicable beans... 41 for (String beanName : beanNames) { 42 Object singletonInstance = getSingleton(beanName); 43 if (singletonInstance instanceof SmartInitializingSingleton) { 44 final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; 45 if (System.getSecurityManager() != null) { 46 AccessController.doPrivileged((PrivilegedAction<Object>) () -> { 47 smartSingleton.afterSingletonsInstantiated(); 48 return null; 49 },getAccessControlContext()); 50 } 51 else { 52 smartSingleton.afterSingletonsInstantiated(); 53 } 54 } 55 } 56 } 在此方法中,注意第12行RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);该方法的作用是将BeanDefinition进行转换,在bean加载时,实例化出来的是GenericBeanDefinition,而spring在实例化bean时需要的是RootBeanDefinition,因此getMergedLocalBeanDefinition方法的作用就是将非RootBeanDefinition转化为RootBeanDefinition以便后续使用。 3.AbstractBeanFactory在实例化bean的时候,最终会落入doGetBean方法中: 1 protected <T> T doGetBean(final String name,@Nullable final Class<T> requiredType, 2 @Nullable final Object[] args,boolean typeCheckOnly) throws BeansException { 3 4 System.out.println("AbstractBeanFactory#doGetBean方法实例化Bean"); 5 final String beanName = transformedBeanName(name); 6 Object bean; 7 8 // Eagerly check singleton cache for manually registered singletons. 9 Object sharedInstance = getSingleton(beanName); 10 if (sharedInstance != null && args == null) { 11 if (logger.isDebugEnabled()) { 12 if (isSingletonCurrentlyInCreation(beanName)) { 13 logger.debug("Returning eagerly cached instance of singleton bean ‘" + beanName + 14 "‘ that is not fully initialized yet - a consequence of a circular reference"); 15 } 16 else { 17 logger.debug("Returning cached instance of singleton bean ‘" + beanName + "‘"); 18 } 19 } 20 bean = getObjectForBeanInstance(sharedInstance,name,beanName,null); 21 } 22 23 else { 24 // Fail if we‘re already creating this bean instance: 25 // We‘re assumably within a circular reference. 26 if (isPrototypeCurrentlyInCreation(beanName)) { 27 throw new BeanCurrentlyInCreationException(beanName); 28 } 29 30 // Check if bean definition exists in this factory. 31 BeanFactory parentBeanFactory = getParentBeanFactory(); 32 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { 33 // Not found -> check parent. 34 String nameToLookup = originalBeanName(name); 35 if (parentBeanFactory instanceof AbstractBeanFactory) { 36 return ((AbstractBeanFactory) parentBeanFactory).doGetBean( 37 nameToLookup,requiredType,args,typeCheckOnly); 38 } 39 else if (args != null) { 40 // Delegation to parent with explicit args. 41 return (T) parentBeanFactory.getBean(nameToLookup,args); 42 } 43 else { 44 // No args -> delegate to standard getBean method. 45 return parentBeanFactory.getBean(nameToLookup,requiredType); 46 } 47 } 48 49 if (!typeCheckOnly) { 50 markBeanAsCreated(beanName); 51 } 52 53 try { 54 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 55 checkMergedBeanDefinition(mbd,args); 56 57 // Guarantee initialization of beans that the current bean depends on. 58 String[] dependsOn = mbd.getDependsOn(); 59 if (dependsOn != null) { 60 for (String dep : dependsOn) { 61 if (isDependent(beanName,dep)) { 62 throw new BeanCreationException(mbd.getResourceDescription(), 63 "Circular depends-on relationship between ‘" + beanName + "‘ and ‘" + dep + "‘"); 64 } 65 registerDependentBean(dep,beanName); 66 try { 67 getBean(dep); 68 } 69 catch (NoSuchBeanDefinitionException ex) { 70 throw new BeanCreationException(mbd.getResourceDescription(), 71 "‘" + beanName + "‘ depends on missing bean ‘" + dep + "‘",ex); 72 } 73 } 74 } 75 76 // Create bean instance. 77 if (mbd.isSingleton()) { 78 sharedInstance = getSingleton(beanName,() -> { 79 try { 80 return createBean(beanName,mbd,args); 81 } 82 catch (BeansException ex) { 83 // Explicitly remove instance from singleton cache: It might have been put there 84 // eagerly by the creation process,to allow for circular reference resolution. 85 // Also remove any beans that received a temporary reference to the bean. 86 destroySingleton(beanName); 87 throw ex; 88 } 89 }); 90 bean = getObjectForBeanInstance(sharedInstance,mbd); 91 } 92 93 else if (mbd.isPrototype()) { 94 // It‘s a prototype -> create a new instance. 95 Object prototypeInstance = null; 96 try { 97 beforePrototypeCreation(beanName); 98 prototypeInstance = createBean(beanName,args); 99 } 100 finally { 101 afterPrototypeCreation(beanName); 102 } 103 bean = getObjectForBeanInstance(prototypeInstance,mbd); 104 } 105 106 else { 107 String scopeName = mbd.getScope(); 108 final Scope scope = this.scopes.get(scopeName); 109 if (scope == null) { 110 throw new IllegalStateException("No Scope registered for scope name ‘" + scopeName + "‘"); 111 } 112 try { 113 Object scopedInstance = scope.get(beanName,() -> { 114 beforePrototypeCreation(beanName); 115 try { 116 return createBean(beanName,args); 117 } 118 finally { 119 afterPrototypeCreation(beanName); 120 } 121 }); 122 bean = getObjectForBeanInstance(scopedInstance,mbd); 123 } 124 catch (IllegalStateException ex) { 125 throw new BeanCreationException(beanName,126 "Scope ‘" + scopeName + "‘ is not active for the current thread; consider " + 127 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",128 ex); 129 } 130 } 131 } 132 catch (BeansException ex) { 133 cleanupAfterBeanCreationFailure(beanName); 134 throw ex; 135 } 136 } 137 138 // Check if required type matches the type of the actual bean instance. 139 if (requiredType != null && !requiredType.isInstance(bean)) { 140 try { 141 T convertedBean = getTypeConverter().convertIfNecessary(bean,requiredType); 142 if (convertedBean == null) { 143 throw new BeanNotOfRequiredTypeException(name,bean.getClass()); 144 } 145 return convertedBean; 146 } 147 catch (TypeMismatchException ex) { 148 if (logger.isDebugEnabled()) { 149 logger.debug("Failed to convert bean ‘" + name + "‘ to required type ‘" + 150 ClassUtils.getQualifiedName(requiredType) + "‘",ex); 151 } 152 throw new BeanNotOfRequiredTypeException(name,bean.getClass()); 153 } 154 } 155 return (T) bean; 156 } 分析: ①9-21行:检查本地单例缓存中是否已经加载过bean,如果没有的话再检查earlySingletonObjects是否已经加载过该bean。 ②26-51行:执行一些校验工作,bean是否为prototype(如果为prototype会抛出异常)、是否为抽象、将bean打上created标记。 ③58-74行:检查bean的depends-on属性,保证depends-on依赖的bean会优先于当前bean被加载。 ④77-91行、93-104行、106-136行:对bean的不同类型进行判断,然后走不同的分支进行bean的创建,我们关注77-91行。 4.AbstractAutowireCapableBeanFactory这里我们关注创建bean的方法,createBeanInstance: 1 protected BeanWrapper createBeanInstance(String beanName,RootBeanDefinition mbd,@Nullable Object[] args) { 2 // Make sure bean class is actually resolved at this point. 3 Class<?> beanClass = resolveBeanClass(mbd,beanName); 4 5 if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { 6 throw new BeanCreationException(mbd.getResourceDescription(), 7 "Bean class isn‘t public,and non-public access not allowed: " + beanClass.getName()); 8 } 9 10 Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); 11 if (instanceSupplier != null) { 12 return obtainFromSupplier(instanceSupplier,beanName); 13 } 14 15 if (mbd.getFactoryMethodName() != null) { 16 return instantiateUsingFactoryMethod(beanName,args); 17 } 18 19 // Shortcut when re-creating the same bean... 20 boolean resolved = false; 21 boolean autowireNecessary = false; 22 if (args == null) { 23 synchronized (mbd.constructorArgumentLock) { 24 if (mbd.resolvedConstructorOrFactoryMethod != null) { 25 resolved = true; 26 autowireNecessary = mbd.constructorArgumentsResolved; 27 } 28 } 29 } 30 if (resolved) { 31 if (autowireNecessary) { 32 return autowireConstructor(beanName,null,null); 33 } 34 else { 35 return instantiateBean(beanName,mbd); 36 } 37 } 38 39 // Need to determine the constructor... 40 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass,beanName); 41 if (ctors != null || 42 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || 43 mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { 44 return autowireConstructor(beanName,ctors,args); 45 } 46 47 // No special handling: simply use no-arg constructor. 48 return instantiateBean(beanName,mbd); 49 } 分析: 该函数前面都是进行一些判断,是否已经存在,是否由父类方法去创建等,这里我们主要关注40-48行。 这里会判断该bean是否使用构造函数进行属性的注入,如果是执行44行,否则执行48行。这里转到48行方法中去: 1 protected BeanWrapper instantiateBean(final String beanName,final RootBeanDefinition mbd) { 2 try { 3 Object beanInstance; 4 final BeanFactory parent = this; 5 if (System.getSecurityManager() != null) { 6 beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () -> 7 getInstantiationStrategy().instantiate(mbd,parent), 8 getAccessControlContext()); 9 } 10 else { 11 beanInstance = getInstantiationStrategy().instantiate(mbd,parent); 12 } 13 BeanWrapper bw = new BeanWrapperImpl(beanInstance); 14 initBeanWrapper(bw); 15 return bw; 16 } 17 catch (Throwable ex) { 18 throw new BeanCreationException( 19 mbd.getResourceDescription(),"Instantiation of bean failed",ex); 20 } 21 } 代码转到11行: 1 public Object instantiate(RootBeanDefinition bd,@Nullable String beanName,BeanFactory owner) { 2 // Don‘t override the class with CGLIB if no overrides. 3 if (!bd.hasMethodOverrides()) { 4 Constructor<?> constructorToUse; 5 synchronized (bd.constructorArgumentLock) { 6 constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod; 7 if (constructorToUse == null) { 8 final Class<?> clazz = bd.getBeanClass(); 9 if (clazz.isInterface()) { 10 throw new BeanInstantiationException(clazz,"Specified class is an interface"); 11 } 12 try { 13 if (System.getSecurityManager() != null) { 14 constructorToUse = AccessController.doPrivileged( 15 (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor); 16 } 17 else { 18 constructorToUse = clazz.getDeclaredConstructor(); 19 } 20 bd.resolvedConstructorOrFactoryMethod = constructorToUse; 21 } 22 catch (Throwable ex) { 23 throw new BeanInstantiationException(clazz,"No default constructor found",ex); 24 } 25 } 26 } 27 return BeanUtils.instantiateClass(constructorToUse); 28 } 29 else { 30 // Must generate CGLIB subclass. 31 return instantiateWithMethodInjection(bd,owner); 32 } 33 } 分析: 这里主要判断使用哪个构造函数进行实例化bean,并且如果方法被覆盖则会采用CGLB来实例化bean,第9行,如果实例化一个接口会抛出异常。 这里直接转到27行: 1 public static <T> T instantiateClass(Constructor<T> ctor,Object... args) throws BeanInstantiationException { 2 Assert.notNull(ctor,"Constructor must not be null"); 3 try { 4 ReflectionUtils.makeAccessible(ctor); 5 /** 6 * 这里通过反射实例化类 7 */ 8 System.out.println("通过BeanUtils#instantiateClass反射生成bean"); 9 System.out.println("最终通过Constructor#newInstance方法生成bean"); 10 // Object object= ctor.newInstance(args); 该句代码多余,下面又用到了 11 return (KotlinDetector.isKotlinType(ctor.getDeclaringClass()) ? 12 KotlinDelegate.instantiateClass(ctor,args) : ctor.newInstance(args)); 13 } 14 catch (InstantiationException ex) { 15 throw new BeanInstantiationException(ctor,"Is it an abstract class?",ex); 16 } 17 catch (IllegalAccessException ex) { 18 throw new BeanInstantiationException(ctor,"Is the constructor accessible?",ex); 19 } 20 catch (IllegalArgumentException ex) { 21 throw new BeanInstantiationException(ctor,"Illegal arguments for constructor",ex); 22 } 23 catch (InvocationTargetException ex) { 24 throw new BeanInstantiationException(ctor,"Constructor threw exception",ex.getTargetException()); 25 } 26 } 最终来到了通过翻身生成bean实例,前几篇文章也有提到。注意第4行makeAccessible,表示即使bean的构造函数是private或者protected,都不会影响bean的构造。 by Shawn Chen,2018.12.25日,晚。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |