导航

0003 - 基于xml的Spring Bean 的创建过程

Posted on 2019-03-02 10:39  皮堡斯  阅读(324)  评论(0)    收藏  举报

一、目录

  1. 前言
  2. 创建 Bean 容器
  3. 加载 Bean 定义
  4. 创建 Bean
  5. Spring Bean 创建过程中的设计模式
  6. 总结

二、前言

2.1 Spring 使用配置

    ApplicationContext context = new ClassPathXmlApplicationContext("spring-config-ioc.xml");
    UserService userService = context.getBean("userService",UserService.class);
    userService.sayHello("zhangsan");

而在 spring-config-ioc.xml 中只是简单的定义了 userService Bean:

    <bean id="userService" class="com.jd.spring.service.ioc.impl.UserServiceImpl">
    </bean>

Spring 使用的版本为 3.2.6.RELEASE,下面我们通过源码一步步来了解下 Bean 的创建过程。

三、创建 Bean 容器

Spring 容器包括两类:BeanFactroy 和 ApplicationContext,ApplicationContext 扩展自 BeanFactory,在之上又增加了一些扩展功能,下面我们以 ClassPathXmlApplicationContext 为例来看下容器的创建过程。

    public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)throws BeansException {
        super(parent);
        setConfigLocations(configLocations);
        if (refresh) {
            //在此进行容器的创建,Bean的加载,创建
            refresh();
        }
    }

refresh 实现步骤如下:

1.prepareRefresh

主要用来验证一些需要的系统变量。

2.obtainFreshBeanFactory

创建 BeanFactory,然后加载 Bean 定义

    protected final void refreshBeanFactory() throws BeansException {
    //判断beanFactory是否为null
    if (hasBeanFactory()) {
        //如果之前已经创建了BeanFactory,调用Bean的destroySingletons方法
        destroyBeans();
        //将beanFactory设置为null
        closeBeanFactory();
    }
    try {
        //创建的容器类为DefaultListableBeanFactory
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        //设置是否允许override,循环引用,QualifierAnnotationAutowireCandidateResolver
        customizeBeanFactory(beanFactory);
        //加载Bean定义
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    }
}

此时可以看到创建的 BeanFactory 为 DefaultListableBeanFactory,通过源码我们可以看到 BeanFactory 和 ApplicationContext 类关系图如下:

enter image description here

3.prepareBeanFactory

添加对 spel 的支持,默认的属性编辑器,同时设置忽略依赖的接口

    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);

4.postProcessBeanFactory

5.invokeBeanFactoryPostProcessors

Bean 容器创建后执行,执行 BeanFactoryPostProcessor 接口的 postProcessBeanFactory 方法。

6.registerBeanPostProcessors

注册 BeanPostProcessor,Bean 创建后执行。BeanPostProcessor提供 postProcessBeforeInitialization、postProcessAfterInitialization 初始化前、初始化后执行方法。

7.initMessageSource

初始化消息资源(国际化)。

8.initApplicationEventMulticaster

注册了 SimpleApplicationEventMulticaster 广播器。

9.onRefresh

初始化一些特殊的 Bean,留给子类来实现。

10.registerListeners

注册事件监听。

11.finishBeanFactoryInitialization

实例化所有单例非延迟加载 Bean,beanFactory.preInstantiateSingletons();

12.finishRefresh

    // Initialize lifecycle processor for this context.
    initLifecycleProcessor();

    // Propagate refresh to lifecycle processor first.
    getLifecycleProcessor().onRefresh();

    // Publish the final event.
    publishEvent(new ContextRefreshedEvent(this));

    // Participate in LiveBeansView MBean, if active.
    LiveBeansView.registerApplicationContext(this);

四、加载 Bean 定义

入口为 AbstractXmlApplicationContext.loadBeanDefinitions 方法,通过 XmlBeanDefinitionReader 来加载 BeanDefinitions。

4.1 获取资源文件

    Resource[] resources = ((ResourcePatternResolver)
    resourceLoader).getResources(location);

获取资源文件分为如下几种情况:

  • 如果 locationPattern 是 classpath*:spring-config-ioc.xml 这种格式的话,那么最终通过 getClassLoader().getResources(path) 来获取资源文件;
  • 如果 locationPattern 是 classpath:spring-config-ioc.xml 这种格式的话,new ClassPathResource(location.substring(CLASSPATHURLPREFIX.length()), getClassLoader());
  • 如果 locationPattern 是 spring-config-ioc.xml 这种格式的话
        try {
            // Try to parse the location as a URL...
            URL url = new URL(location);
            return new UrlResource(url);
        }
        catch (MalformedURLException ex) {
            // No URL -> resolve as resource path.
            return getResourceByPath(location);
        }

最终返回 new ClassPathContextResource(path, getClassLoader())。

4.2 加载 Bean 定义

加载 Bean 定义的入口为 XmlBeanDefinitionReader.loadBeanDefinitions,核心方法如下:

    Document doc = this.documentLoader.loadDocument(
                    inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
            return registerBeanDefinitions(doc, resource);

首先通过 documentLoader 获取到 xml 文件对应的 Document 对象,然后再解析 Document 对象,最终注册 registerBeanDefinitions。这里面的方法调用层级比较多,但是都相对比较简单,我就不一一列出了,我只列出一些核心,关键的代码,其它代码大家可以自己跟下。

在解析的时候 Spring 会留有解析前处理,解析后处理方法,供子类实现。

    //创建Bean解析的代理类,同时解析出在beans中定义的default属性,如default-lazy-init="default"
    //default-autowire="default"
    this.delegate = createDelegate(this.readerContext, root, parent);
    preProcessXml(root);
    parseBeanDefinitions(root, this.delegate);
    postProcessXml(root);

解析 BeanDefinitions:

    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        if (delegate.isDefaultNamespace(root)) {
            NodeList nl = root.getChildNodes();
            for (int i = 0; i < nl.getLength(); i++) {
                Node node = nl.item(i);
                if (node instanceof Element) {
                    Element ele = (Element) node;
                    if (delegate.isDefaultNamespace(ele)) {
                        //解析默认标签元素
                        parseDefaultElement(ele, delegate);
                    }
                    else {
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        }
        else {
            //解析自定义标签
            delegate.parseCustomElement(root);
        }
    }

如果节点元素的 namespaceURI 为http://www.springframework.org/schema/beans,那么认为是默认元素,否则认为是自定义元素。自定义元素通过 NameSpaceHandler 类类处理,不同的标签有不同的处理类。

默认元素主要包括如下 4 种:

  • import:解析 import 元素,然后加载 resource 指定的配置文件,过程同上
  • alias:解析别名
  • Bean:解析Bean,下面重点讲解
  • Beans:解析Beans,循环解析Beans下的元素,过程同上

解析 Bean 定义过程如下:

    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {
            //将BeanDefinition注册到BeanFactory
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
        }
        catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to register bean definition with name '" +
                    bdHolder.getBeanName() + "'", ele, ex);
        }
        //注册完成后发送事件通知
        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }

解析过程主要包括 3 部分:解析 Bean 定义,然后注册到 BeanFactory,最后发送注册完成通知。

4.2 解析 Bean 定义

    String id = ele.getAttribute(ID_ATTRIBUTE);
    String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
    AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
    String[] aliasesArray = StringUtils.toStringArray(aliases);
    return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);

parseBeanDefinitionElement 过程如下:

    className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
    AbstractBeanDefinition bd = createBeanDefinition(className, parent);
    parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);

    parseMetaElements(ele, bd);
    parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
    parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

    parseConstructorArgElements(ele, bd);
    parsePropertyElements(ele, bd);
    parseQualifierElements(ele, bd);

1.创建 BeanDefinition 对象

创建 GenericBeanDefinition 对象。

2.解析 BeanDefinition 属性

解析 scope、singleton、abstract、lazy-init、autowire、dependency-check、depends-on、autowire-candidate、primary、init-method、destroy-method、factory-method、factory-bean 属性。scope、singleton 不能同时存在。

3.解析 Meta 元素

解析 bean 下的 meta 元素,如

    <meta key="name" value="zhangsan"/>

通过 BeanDefinition.getAttribute 获取属性值。

4.解析 LookupOverride 子元素

解析 lookup 子元素并注册到 BeanDefinitions,BeanDefinition 持有 MethodOverrides 引用:

    private MethodOverrides methodOverrides = new MethodOverrides();

    MethodOverrides:
    private final Set<MethodOverride> overrides = new HashSet<MethodOverride>(0);

5.解析 ReplacedMethod 子元素

解析 replace 子元素并注册到 BeanDefinitions。

6.解析构造器元素

解析构造器元素 constructor-arg。

7.解析属性元素

解析 property 属性,属性值:

    Object val = parsePropertyValue(ele, bd, propertyName);
    PropertyValue pv = new PropertyValue(propertyName, val);
    parseMetaElements(ele, pv);
    pv.setSource(extractSource(ele));
    bd.getPropertyValues().addPropertyValue(pv);

属性 name 的解析相对简单,属性 value 的解析比较复杂,涉及到 ref、value,还有可能是子元素 array、list、set、map、props,这里就不展开说明了,感兴趣的可以自己看下。

8.解析 Qualifier 元素

解析 Qualifier 元素。

4.3 注册 Bean 定义

通过 BeanDefinitionRegistry 来注册 BeanDefinition,最终是将 BeanDefinition 保存在 BeanFactory 中,

    this.beanDefinitionMap.put(beanName, beanDefinition);

BeanFactory持有beanDefinitionMap引用:

    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);

4.4 发送通知

bean 注册完成后,发送通知,Listener 需要实现 ReaderEventListener 接口,

    public void fireComponentRegistered(ComponentDefinition componentDefinition) {
        this.eventListener.componentRegistered(componentDefinition);
    }

五、创建 Bean

在创建 ApplicationContext 时会默认初始化所有非懒加载的单例 bean(BeanFactory 容器的话是在 getBean 时创建 bean 对象)。创建 bean 的入口为 AbstractBeanFactory.getBean 方法,核心代码如下:

        // Eagerly check singleton cache for manually registered singletons.
        Object sharedInstance = getSingleton(beanName);

首先从"缓存"中查找 bean 是否已经创建,如果创建的话直接返回创建的 bean,否则执行创建 bean 的逻辑。如果 scope 配置为 prototype,那么每次 getBean 时都会创建 bean。

1.getSingleton

从缓存中获取 bean,此处很关键,用来解决 Spring 循环依赖问题。

    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }

首先从 singletonObjects 中获取对象,如果 singletonObjects 不存在的话那么从 earlySingletonObjects 中获取对象,earlySingletonObjects 存放的是创建中的对象(bean 已创建,但是还未初始化完成),singletonFactories 存放的是 bean 和 ObjectFactory 的关系,在 bean 创建完成后会保存 bean 和 ObjectFactory 的关系。singletonFactories 和 earlySingletonObjects 互斥。

2.合并 BeanDefinition

3.创建 bean dependsOn 依赖的 beans

如果我们配置了 bean 标签的 depends-on 属性,那么在创建 bean 前会首先创建依赖的 beans。

4.创建单例对象

    resolveBeanClass(mbd, beanName);

    mbd.prepareMethodOverrides();

    // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
    Object bean = resolveBeforeInstantiation(beanName, mbd);
    if (bean != null) {
        return bean;
    }
    Object beanInstance = doCreateBean(beanName, mbd, args);
  • resolveBeforeInstantiation

在 bean 实例化前、后执行,可以更改 bean 的实例化对象,如配置:

    <bean class="com.jd.spring.processor.MyInstantiationAwareBeanPostProcessor"/>

MyInstantiationAwareBeanPostProcessor类实现InstantiationAwareBeanPostProcessor,然后重写postProcessBeforeInstantiation方法:


    public Object postProcessBeforeInstantiation(Class<?> beanClass,
            String beanName) throws BeansException {
        if (beanName != null && beanName.equals("helloWorldService")) {
            return new HelloWorldServiceProxy();
        }
        return null;
    }

这样的话 helloWorldService 对应的 bean 为 HelloWorldServiceProxy。

  • doCreateBean

创建 bean 的实现方法,下面我们通过单独的章节来重点说明。

5.创建原型对象

    try {
            beforePrototypeCreation(beanName);
            prototypeInstance = createBean(beanName, mbd, args);
        }
    finally {
            afterPrototypeCreation(beanName);
    }
    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);


getObjectForBeanInstance,如果创建的bean为FactoryBean,调用FactoryBean.getObject方法生成最终的bean。

5.1 doCreateBean

方法入口为 AbstractAutowireCapableBeanFactory.doCreateBean,doCreateBean 核心方法如下:

    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
    Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            mbd.postProcessed = true;
        }
    }

    addSingletonFactory(beanName, new ObjectFactory<Object>() {
                public Object getObject() throws BeansException {
                    return getEarlyBeanReference(beanName, mbd, bean);
                }
            });

    populateBean(beanName, mbd, instanceWrapper);
    if (exposedObject != null) {
            exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
5.1.1 createBeanInstance

创建 bean 实例,其本质是通过反射调用默认或有参的构造方法来创建 bean 实例,下面我们来看下具体的实现细节。

    //获取beanClass,通过Class.forName来获取
    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());
    }
    //如果配置了factory-method,那么通过工厂方法来创建bean,这个稍后分析下

    if (mbd.getFactoryMethodName() != null)  {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }
    // 获取构造器,可能通过默认构造器来创建bean,也可能通过有参构造器来创建bean
    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);

instantiateUsingFactoryMethod

通过工厂方法来创建,如果我们在定义 bean 时配置了 factory-method 属性,如

   <bean id="userServiceFactory" class="com.jd.spring.service.ioc.impl.UserServiceFactory" ></bean>
   <bean id="userService" class="com.jd.spring.service.ioc.impl.UserServiceImpl" factory-bean="userServiceFactory" factory-method="getUserService" >
       <property name="userServiceB" ref="userServiceB"> </property>
   </bean>

那么将会通过 userServiceFactory的getUserService 方法来创建 bean,instantiateUsingFactoryMethod 方法实现如下:

    protected BeanWrapper instantiateUsingFactoryMethod(
            String beanName, RootBeanDefinition mbd, Object[] explicitArgs) {

        return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
    }

核心步骤如下:

1.获取工厂 bean

    String factoryBeanName = mbd.getFactoryBeanName();
    if (factoryBeanName != null) {
        if (factoryBeanName.equals(beanName)) {
            throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
                    "factory-bean reference points back to the same bean definition");
        }
        factoryBean = this.beanFactory.getBean(factoryBeanName);
        if (factoryBean == null) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "factory-bean '" + factoryBeanName + "' returned null");
        }
        factoryClass = factoryBean.getClass();
        isStatic = false;
    }
    else {
        // It's a static factory method on the bean class.
        if (!mbd.hasBeanClass()) {
            throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
                    "bean definition declares neither a bean class nor a factory-bean reference");
        }
        factoryBean = null;
        factoryClass = mbd.getBeanClass();
        isStatic = true;
    }

也就是说如果配置了 factory-bean 属性,那么工厂类为配置的 factory-bean,否则工厂类为当前 bean,但是要求工厂方法为静态方法。

2.获取工厂方法

    rawCandidates = (mbd.isNonPublicAccessAllowed() ?
        ReflectionUtils.getAllDeclaredMethods(factoryClazz) : factoryClazz.getMethods());
    List<Method> candidateSet = new ArrayList<Method>();
    for (Method candidate : rawCandidates) {
        if (Modifier.isStatic(candidate.getModifiers()) == isStatic &&
                candidate.getName().equals(mbd.getFactoryMethodName()) &&
                mbd.isFactoryMethod(candidate)) {
            candidateSet.add(candidate);
        }
    }
    Method[] candidates = candidateSet.toArray(new Method[candidateSet.size()]);
    AutowireUtils.sortFactoryMethods(candidates);

获取工厂类中的工厂方法,并进行方法排序,因为会存在方法重载的情况,排序规则如下:

    public static void sortFactoryMethods(Method[] factoryMethods) {
        Arrays.sort(factoryMethods, new Comparator<Method>() {
            public int compare(Method fm1, Method fm2) {
                boolean p1 = Modifier.isPublic(fm1.getModifiers());
                boolean p2 = Modifier.isPublic(fm2.getModifiers());
                if (p1 != p2) {
                    return (p1 ? -1 : 1);
                }
                int c1pl = fm1.getParameterTypes().length;
                int c2pl = fm2.getParameterTypes().length;
                return (new Integer(c1pl)).compareTo(c2pl) * -1;
            }
        });
    }

先按方法修饰符进行排序,public 方法在前,non-public 方法在后;再按照方法参数个数进行排序,方法参数多的在前,少的在后。

然后按照配置的 ConstructorArguments 来匹配工厂方法。

3.反射执行方法创建 bean

beanInstance = beanFactory.getInstantiationStrategy().instantiate(
    mbd, beanName, beanFactory, factoryBean, factoryMethodToUse, argsToUse);

最终通过反射创建 bean,factoryMethod.invoke(factoryBean, args);

autowireConstructor

使用有参的构造方法来创建 bean:

    Class<?> beanClass = mbd.getBeanClass();
    try {
        candidates = (mbd.isNonPublicAccessAllowed() ?
                beanClass.getDeclaredConstructors() : beanClass.getConstructors());
    }
    AutowireUtils.sortConstructors(candidates);

取得 beanClass 下的构造方法,同样进行排序,排序规则也是先按方法修饰符进行排序,public 方法在前,non-public 方法在后;再按照方法参数个数进行排序,方法参数多的在前,少的在后。

然后按照配置的 ConstructorArguments 来匹配构造方法,匹配规则是按照构造方法参数个数和参数类型进行匹配。

    if (explicitArgs == null) {
        argsHolderToUse.storeCache(mbd, constructorToUse);
    }

将匹配到的构造方法进行缓存,防止后续重复计算。找到匹配的构造方法后,然后通过反射创建 bean。

beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
                mbd, beanName, this.beanFactory, constructorToUse, argsToUse);

instantiateBean

使用默认的构造方法来创建 bean,同样也是通过反射创建 bean,代码如下:

beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
5.1.2 applyMergedBeanDefinitionPostProcessors
5.1.3 addSingletonFactory

如果对象为单例,并且允许提前曝光,并且 bean 正在创建中,那么将 bean 和 ObjectFactory 放入到 singletonFactory 中,此处的作用是用来解决循环依赖的问题。

5.1.4 填充属性

populateBean 核心代码如下:

//获取bean配置下的子元素property
PropertyValues pvs = mbd.getPropertyValues();

//如果指定了自动注入的模式,获取自动注入的属性
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
        mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
    MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

    // Add property values based on autowire by name if applicable.
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
        autowireByName(beanName, mbd, bw, newPvs);
    }

    // Add property values based on autowire by type if applicable.
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
        autowireByType(beanName, mbd, bw, newPvs);
    }

    pvs = newPvs;
}

//设置属性值
applyPropertyValues(beanName, mbd, bw, pvs);

autowireByName

autowire="byName" 根据名称自动注入,使用自动注入的好处是可以解决<bean> 标签下 <property> 标签过多的问题。

    //查找所有未配置的属性,在bean class中存在,但是未在xml配置文件中配置的属性
    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    for (String propertyName : propertyNames) {
        if (containsBean(propertyName)) {
            Object bean = getBean(propertyName); //获取bean
            pvs.add(propertyName, bean);
            registerDependentBean(propertyName, beanName);

        }
    }

autowireByType

autowire="byType" 根据类型自动注入。通过 DefaultListableBeanFactory.doResolveDependency 来获取属性的值,然后同样添加到 pvs,pvs.add(propertyName, bean);

在获取值的时候会根据 type 类型来做相应处理,如Array、Collection、Map,我们以常见的注入 bean 属性为例来看下实现代码:

//根据类型查找候选的bean
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
    if (descriptor.isRequired()) {
        raiseNoSuchBeanDefinitionException(type, "", descriptor);
    }
    return null;
}
if (matchingBeans.size() > 1) {
    String primaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor);

    //如果根据类型匹配到多个bean,并且没有指定primaryBeanName属性的话那么会抛出类似expected single matching bean but found 2 这样的异常
    if (primaryBeanName == null) {
        throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
    }
    if (autowiredBeanNames != null) {
        autowiredBeanNames.add(primaryBeanName);
    }
    return matchingBeans.get(primaryBeanName);
}
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
if (autowiredBeanNames != null) {
    autowiredBeanNames.add(entry.getKey());
}
return entry.getValue();

applyPropertyValues

TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
    converter = bw;
}
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

遍历配置的 property 子元素,然后获取 value/ref 对应的值

String propertyName = pv.getName(); 
Object originalValue = pv.getValue();
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); //获取属性值,可能为字符串,也可能是bean,list,map
Object convertedValue = resolvedValue;
boolean convertible = bw.isWritableProperty(propertyName) &&
                    !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
    convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}

// Set our (possibly massaged) deep copy.
try {
    //deepCopy为PropertyValue集合,记录了属性名和属性值
    bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}

上面最重要的两步为转换属性的值和设置属性的值,下面我们分别来看下。

  • convertForProperty

转换属性的值:

private Object convertForProperty(Object value, String propertyName, BeanWrapper bw, TypeConverter converter) {
    if (converter instanceof BeanWrapperImpl) {
        return ((BeanWrapperImpl) converter).convertForProperty(value, propertyName);
    }
    else {
        PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
        MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
        return converter.convertIfNecessary(value, pd.getPropertyType(), methodParam);
    }
}

public Object convertForProperty(Object value, String propertyName) throws TypeMismatchException {
    //获取属性描述符,记录了属性的数据类型,如String,List,Map
    PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(propertyName); 
    if (pd == null) {
        throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
                "No property '" + propertyName + "' found");
    }
    return convertForProperty(propertyName, null, value, pd);
}

最终通过 typeConverterDelegate 代理类来执行:

this.typeConverterDelegate.convertIfNecessary(propertyName, oldValue, newValue, requiredType, td);

转换过程如下:

1.查找是否定义了数据类型对应的自定义属性编辑器PropertyEditor,如果定义了自定义的PropertyEditor,则通过getValue获取值 2.判断是否定义了ConversionService,通过conversionService.convert来转换属性值3.convertToTypedArray

int arrayLength = Array.getLength(input);
Object result = Array.newInstance(componentType, arrayLength);
for (int i = 0; i < arrayLength; i++) {
    Object value = convertIfNecessary(
            buildIndexedPropertyName(propertyName, i), null, Array.get(input, i), componentType);
    Array.set(result, i, value);
}

4.convertToTypedCollection

convertedCopy = CollectionFactory.createApproximateCollection(original, original.size());
Object element = it.next();
String indexedPropertyName = buildIndexedPropertyName(propertyName, i);
Object convertedElement = convertIfNecessary(indexedPropertyName, null, element,
        (elementType != null ? elementType.getType() : null) , elementType);
try {
    convertedCopy.add(convertedElement);
}

遍历集合中的元素,然后生成转换后的集合。如果是 List 的话生成 ArrayList,Set 的话如果是排序 Set 的话生成 TreeSet,否则生成 LinkedHashSet

5.convertToTypedMap

//如果map类型为SortedMap,那么创建TreeMap;否则创建LinkedHashMap
convertedCopy = CollectionFactory.createApproximateMap(original, original.size());

while (it.hasNext()) {
    Map.Entry entry = (Map.Entry) it.next();
    Object key = entry.getKey();
    Object value = entry.getValue();
    String keyedPropertyName = buildKeyedPropertyName(propertyName, key);
    Object convertedKey = convertIfNecessary(keyedPropertyName, null, key,
            (keyType != null ? keyType.getType() : null), keyType);
    Object convertedValue = convertIfNecessary(keyedPropertyName, null, value,
            (valueType!= null ? valueType.getType() : null), valueType);
    try {
        convertedCopy.put(convertedKey, convertedValue);
    }
}
  • setPropertyValues
 //deepCopy为PropertyValue集合,记录了属性名和属性值
 bw.setPropertyValues(new MutablePropertyValues(deepCopy));
final Method writeMethod = (pd instanceof GenericTypeAwarePropertyDescriptor ?
        ((GenericTypeAwarePropertyDescriptor) pd).getWriteMethodForActualAccess() :
        pd.getWriteMethod());
writeMethod.invoke(this.object, value);  

其实现本质就是获取属性对应的 set 方法,然后调用反射进行设置。需要注意情况如下:

1.如果定义了属性,但是未存在相应set方法,则抛出异常

Bean property 'name' is not writable or has an invalid setter method

2.如果属性为List,Map等集合属性,首先通过相应的read方法来获取已有值,然后再合并新的值。

5.1.5 bean 初始化
    invokeAwareMethods(beanName, bean);
    wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    invokeInitMethods(beanName, wrappedBean, mbd);
    wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

1.执行 Aware 方法

    if (bean instanceof BeanNameAware) {
        ((BeanNameAware) bean).setBeanName(beanName);
    }
    if (bean instanceof BeanClassLoaderAware) {
        ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
    }
    if (bean instanceof BeanFactoryAware) {
        ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
    }

2.执行 BeanPostProcessor.postProcessBeforeInitialization

执行 BeanPostProcessor 的初始化前方法,BeanPostProcessor 需要在 xml 中配置,如

    <bean class="com.jd.spring.processor.MyBeanPostPrcessor"/>

3.执行 bean 初始化方法

    ((InitializingBean) bean).afterPropertiesSet();
    invokeCustomInitMethod(beanName, bean, mbd);

首先执行 afterPropertiesSet 方法(如果实现 InitializingBean 接口的话),然后再执行自定义的初始化方法 init-method。

4.执行 BeanPostProcessor.postProcessAfterInitialization

执行 BeanPostProcessor 的初始化后方法,BeanPostProcessor 需要在 xml中 配置,如

    <bean class="com.jd.spring.processor.MyBeanPostPrcessor"/>

bean 初始化过程结果如下:

enter image description here