/* * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.beans.factory.support; import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; /** * Utility methods that are useful for bean definition reader implementations. * Mainly intended for internal use. * * @author Juergen Hoeller * @author Rob Harrop * @see PropertiesBeanDefinitionReader * @see org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader * @since 1.1 */ public abstract class BeanDefinitionReaderUtils { /** * Separator for generated bean names. If a class name or parent name is not * unique, "#1", "#2" etc will be appended, until the name becomes unique. */ public static final String GENERATED_BEAN_NAME_SEPARATOR = BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR; /** * Create a new GenericBeanDefinition for the given parent name and class name, * eagerly loading the bean class if a ClassLoader has been specified. * * @param parentName the name of the parent bean, if any * @param className the name of the bean class, if any * @param classLoader the ClassLoader to use for loading bean classes * (can be {@code null} to just register bean classes by name) * @return the bean definition * @throws ClassNotFoundException if the bean class could not be loaded */ public static AbstractBeanDefinition createBeanDefinition( @Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException { /** * GenericBeanDefinition 是自 2.5 版本以后新加入的bean文件配置属性定义类,是一站式服务类 * 是AbstractBeanDefinition 其中一种解析配置类 */ System.out.println("GenericBeanDefinition 是自 2.5 版本以后新加入的bean文件配置属性定义类,是一站式服务类\n" + "是AbstractBeanDefinition 其中一种解析配置类"); GenericBeanDefinition bd = new GenericBeanDefinition(); bd.setParentName(parentName); if (className != null) { if (classLoader != null) { /** * 如果 classLoader 不为空, 则使用以传人的 classLoader 同-虚拟机的加载类对象,否则只是记录className */ System.out.println("如果 classLoader 不为空, 则使用以传人的 classLoader 同-虚拟机的加载类对象,否则只是记录className"); bd.setBeanClass(ClassUtils.forName(className, classLoader)); } else { bd.setBeanClassName(className); } } System.err.println("通过GenericBeanDefinition设置定义的父类" + bd.getParentName()); System.err.println("通过GenericBeanDefinition设置定义的父类" + bd.toString()); return bd; } /** * Generate a bean name for the given top-level bean definition, * unique within the given bean factory. * * @param beanDefinition the bean definition to generate a bean name for * @param registry the bean factory that the definition is going to be * registered with (to check for existing bean names) * @return the generated bean name * @throws BeanDefinitionStoreException if no unique name can be generated * for the given bean definition * @see #generateBeanName(BeanDefinition, BeanDefinitionRegistry, boolean) */ public static String generateBeanName(BeanDefinition beanDefinition, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { return generateBeanName(beanDefinition, registry, false); } /** * Generate a bean name for the given bean definition, unique within the * given bean factory. * * @param definition the bean definition to generate a bean name for * @param registry the bean factory that the definition is going to be * registered with (to check for existing bean names) * @param isInnerBean whether the given bean definition will be registered * as inner bean or as top-level bean (allowing for special name generation * for inner beans versus top-level beans) * @return the generated bean name * @throws BeanDefinitionStoreException if no unique name can be generated * for the given bean definition */ public static String generateBeanName( BeanDefinition definition, BeanDefinitionRegistry registry, boolean isInnerBean) throws BeanDefinitionStoreException { String generatedBeanName = definition.getBeanClassName(); if (generatedBeanName == null) { if (definition.getParentName() != null) { generatedBeanName = definition.getParentName() + "$child"; } else if (definition.getFactoryBeanName() != null) { generatedBeanName = definition.getFactoryBeanName() + "$created"; } } if (!StringUtils.hasText(generatedBeanName)) { throw new BeanDefinitionStoreException("Unnamed bean definition specifies neither " + "'class' nor 'parent' nor 'factory-bean' - can't generate bean name"); } if (isInnerBean) { // Inner bean: generate identity hashcode suffix. return generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(definition); } // Top-level bean: use plain class name with unique suffix if necessary. return uniqueBeanName(generatedBeanName, registry); } /** * Turn the given bean name into a unique bean name for the given bean factory, * appending a unique counter as suffix if necessary. * * @param beanName the original bean name * @param registry the bean factory that the definition is going to be * registered with (to check for existing bean names) * @return the unique bean name to use * @since 5.1 */ public static String uniqueBeanName(String beanName, BeanDefinitionRegistry registry) { String id = beanName; int counter = -1; // Increase counter until the id is unique. String prefix = beanName + GENERATED_BEAN_NAME_SEPARATOR; while (counter == -1 || registry.containsBeanDefinition(id)) { counter++; id = prefix + counter; } return id; } /** * Register the given bean definition with the given bean factory. * * @param definitionHolder the bean definition including name and aliases * @param registry the bean factory to register with * @throws BeanDefinitionStoreException if registration failed * * 解析的beanDefinition都会被注册到BeanDefinitionRegistry类型的实例registry中, * 而对于beanDefinition的注册分成了两部分:通过beanName的注册以及通过别名进行注册. */ public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { /** 使用beanName做唯一标识注册*/ System.err.println("对BeanDefinition(Bean定义)进行注册"); // Register bean definition under primary name. String beanName = definitionHolder.getBeanName(); System.err.println("获取bean的名称:" + beanName); registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); /** 注册所有的别名 此处调用的是 SimpleAliasRegister*/ // Register aliases for bean name, if any. String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String alias : aliases) { registry.registerAlias(beanName, alias); } } } /** * Register the given bean definition with a generated name, * unique within the given bean factory. * * @param definition the bean definition to generate a bean name for * @param registry the bean factory to register with * @return the generated bean name * @throws BeanDefinitionStoreException if no unique name can be generated * for the given bean definition or the definition cannot be registered */ public static String registerWithGeneratedName( AbstractBeanDefinition definition, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { String generatedName = generateBeanName(definition, registry, false); registry.registerBeanDefinition(generatedName, definition); return generatedName; } }