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

一、目录

  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

猜你喜欢

转载自www.cnblogs.com/Pibaosi/p/10460046.html