Spring MVC 解读——@Autowired

Spring MVC 解读——@Autowired

一、@Autowired

    作为一个Spring开发者对@Autowired注解必定是非常了解了, 顾名思义自动装配,应该是Spring会自动将我们标记为@Autowired的元素装配好,与其猜测不如看看它的定义:

1@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, 2                         ElementType.ANNOTATION_TYPE}) 3@Retention(RetentionPolicy.RUNTIME) 4@Documented 5public @interface Autowired { 6    boolean required() default true; 7}

   很明显这个注解可以用到构造器,变量域,方法,注解类型上。文档上这样描述:将一个构造器,变量域,setter方法,config方法标记为被Spring DI 工具自动装配。换句话说,我们视图从bean 工厂中获取一个bean时,Spring会自动为我们装配该bean中标记为@Autowired的元素,而无需我们手动完成。这些相信大家都明白,但问题是,Spring是怎样做到的?在Spring MVC中怎样做到的?什么时候进行的自动装配?下面我们就来探究下这些问题。

二、BeanPostProcessor

    在@Autowired的定义中有下面一段话:

1Note that actual injection is performed through a BeanPostProcessor  2which in turn means that you cannot use @Autowired to inject references into BeanPostProcessor 3or BeanFactoryPostProcessor types.  4Please consult the javadoc for the AutowiredAnnotationBeanPostProcessor class  5(which, by default, checks for the presence of this annotation).

   意思是:实际的注入装配动作是由BeanPostProcessor执行的,翻过来说你不能将@Autowired注解用于BeanPostProcessor或BeanFactoryPostProcessor类型上。请查看AutowiredAnnotationBeanPostProcessor文档(默认情况下,被用来检查@Autowired注解)。

文档说的很清楚了,BeanPostProcessor来执行自动装配,并且默认情况下使用AutowiredAnnotationBeanPostProcessor实现类完成。那我们不妨看一下他们的定义:

1public interface BeanPostProcessor { 2    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; 3    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; 4}

   BeanPostProcessor就一个回调接口,定义了两个方法声明,一个是实例化前被调用,一个是实例化后被调用,没啥好看的,我们直接看看它的实现类AutowiredAnnotationBeanPostProcessor:

1BeanPostProcessor implementation that autowires annotated fields, setter methods and arbitrary  2config methods. Such members to be injected are detected through a Java 5 annotation:  3by default, Spring's @Autowired and @Value annotations.Also supports JSR-330's @Inject  4annotation, if available, as a direct alternative to Spring's own @Autowired. 5 6Note: A default AutowiredAnnotationBeanPostProcessor will be registered by  7the "context:annotation-config" and "context:component-scan" XML tags. 8 9NOTE: Annotation injection will be performed before XML  10injection; thus the latter configuration will override the former for properties  11wired through both approaches.

   上面是AutowiredAnnotationBeanPostProcessor类的描述文档摘要,大致意思是:这是BeanPostProcessor接口的一个实现,用来自动装配注解的变量域,setter方法和任意的config方法。这些被注入的元素是通过检测Java 5的注解完成的:默认情况下是@Autowired和@Value注解。同样也支持JSR-330的@Inject注解。并且,context:annotation-config/context:component-scan/XML标签可以默认注册AutowiredAnnotationBeanPostProcessor到bean工厂中。最后,注解注入会在XML注入之前执行;因此后面的配置会覆盖前面已经装配好的元素。

是不是很清楚了?Spring的文档总是这么详细,要么说是教科书呢,废话不多说,我们才刚进正题呢,既然我们清楚了是AutowiredAnnotationBeanPostProcessor实例执行了自动装配,那么它做了什么呢?

三、磨刀砍柴   

在正式查看源码前,我先大致的讲一下整个装配的过程,以便后面理解起来轻松些。其实整体思路还是很简单的,我们举个简单的例子:

1//==================================Controller 2@Controller 3public class SimpleController { 4    @Autowired 5    private SimpleService simpleService; 6} 7//==================================Service 8@Service("simpleService") 9public class SimpleServiceImpl implements SimpleService { 10    @Autowired 11    private SimpleDao simpleDao; 12} 13//===================================Repository 14@Repository("simpleDao") 15public class SimpleDaoImpl implements SimpleDao { 16}

1)在某一时刻Spring调用了 Bean工厂 的 getBean(beanName) 方法。beanName可能是simpleController,或者simpleService,simpleDao,顺序没关系(因为后面会有依赖关系的处理)。我们假设simpleController吧。

2)getBean方法首先会调用Bean工厂中定义的getSingleton(beanName)方法,来判断是否存在该名字的bean单例,若果存在则返回,方法调用结束。

3)否则,Spring会检查是否存在父工厂,如果有则返回,方法调用结束。

4)否则,Spring 会检查该bean 定义(BeanDefinition实例,用来描述Bean结构,上篇文章讲到过,component-scan 扫描后,就是将beanDefinition实例放入Bean工厂,此时Bean还没有被实例化。)是否有依赖关系,如果有,执行1)步,获取依赖的bean实例。

5)否则,Spring会尝试创建这个bean实例,创建实例前,Spring会检查确定调用的构造器,并实例化该Bean。

6)实例化完成后,Spring会调用Bean工厂的populateBean方法来填充bean实例的属性,也就是我们前面提到的自动转配了。populateBean方法便是调用了BeanPostProcessor实例来完成属性元素的自动装配工作。

7)在元素装配过程中,Spring会检查被装配的属性是否存在自动装配的其他属性,然后递归调用getBean方法,直到所有@Autowired的元素都被装配完成。如在装配simpleController中的simpleService属性时,发现SimpleServiceImpl实例中存在@Autowired属性simpleDao,然后调用getBean(simpleDao)方法,同样会执行1)-7)整个过程。所以可以看成一个递归过程。

8)装配完成后,Bean工厂会将所有的bean实例都添加到工厂中来。

注:我们知道Spring MVC是多线程单实例的MVC框架,就是说,对于同一个Controller,只会生成一个实例来处理所有的请求,因此bean实例只会实例化一次,并被存放在工厂中,以供其他请求使用。

好了,大致了解整个流程后我们看一下Spring的具体行为吧。

四、Bean 工厂

    前面多次提到了Bean工厂,但一直没有说它到底是个什么,这里我们就彻底弄清楚吧,省的云里雾里,这样我们后面讲到Bean工厂就不会晕了。看过上一篇博客(context:component-scan/)的朋友可能记得DefaultListableBeanFactory这个类,当时是它保存了扫描到的组件--Bean Definition实例。那他是否是我们所说的Bean工厂呢?是否保存了Bean实例呢?答案是:对。

我们可以看到DefaultLiableBeanFactory继承自DefaultSingletonBeanRegistry,AbstractBeanFactory,AbstractAutowireCapableBeanFactory。下面就列出了一下相关的Bean工厂中的属性和方法:

1//========================================================================================== 2//==============================DefaultListableBeanFactory================================ 3//========================================================================================== 4//beanName-beanDefinition 的映射表 5private final Map<String, BeanDefinition> beanDefinitionMap =  6                                            new ConcurrentHashMap<String, BeanDefinition>(64); 7//beanName 列表 8private final List<String> beanDefinitionNames = new ArrayList<String>(); 9//========================================================================================== 10//=============================AbstractBeanFactory================================= 11//========================================================================================== 12//注册了所有的BeanPostProcessor实例,包括前面提到的用来处理@Autowired注解的 13//AutowiredAnnotationBeanPostProcessor  14private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<BeanPostProcessor>(); 15//可能存在的父亲Bean工厂 16private BeanFactory parentBeanFactory; 17//========================================================================================== 18//==============================DefaultSingletonBeanRegistry================================ 19//========================================================================================== 20//beanName--bean单例的映射表 21private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64); 22//注册过的beanName集合 23private final Set<String> registeredSingletons = new LinkedHashSet<String>(64); 24//beanName与该bean所依赖的Beans集合的映射表,如simpleDao依赖与simpleService,如果还有其他 25service使用该Dao,如simpleService2那么是simpleDao->[simpleService,simpleService2] 26private final Map<String, Set<String>> dependentBeanMap  27                                            = new ConcurrentHashMap<String, Set<String>>(64); 28//恰好与上面相反,beanName与该bean所包含的beans的集合映射表,如simpleController->[simpleService] 29private final Map<String, Set<String>> dependenciesForBeanMap  30                                            = new ConcurrentHashMap<String, Set<String>>(64);

   可以看到Bean工厂中即存有bean definition的映射表,也存有bean name的别表,以及bean实例的映射表,还有依赖关系图。理解了这个对下面的实例化以及装配过程会有很大帮助。

五,实例化与装配

  下面我们就从头到尾看一下整个的实例化和装配过程:

1public Object getBean(String name) throws BeansException { 2    return doGetBean(name, null, null, false); 3} 4 5@SuppressWarnings("unchecked") 6protected <T> T doGetBean(final String name, final Class<T> requiredType,  7                          final Object[] args, boolean typeCheckOnly)throws BeansException { 8        //去掉工厂bean的前缀或者将别名转化为规范名 9        final String beanName = transformedBeanName(name); 10        Object bean; 11        // 检查是否有已经注册的bean实例 12        Object sharedInstance = getSingleton(beanName); 13        if (sharedInstance != null && args == null) { 14            //如果是工厂bean,获取工厂bean创建的bean 15            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); 16        } 17        else { 18            //判断是否有父工厂,并且其中是否存在该bean实例? 19            BeanFactory parentBeanFactory = getParentBeanFactory(); 20            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { 21                String nameToLookup = originalBeanName(name); 22                if (args != null) { 23                    return (T) parentBeanFactory.getBean(nameToLookup, args); 24                } 25                else { 26                    return parentBeanFactory.getBean(nameToLookup, requiredType); 27                } 28            } 29            if (!typeCheckOnly) { 30                markBeanAsCreated(beanName);//将该beanName标记为已经实例化 31            } 32            //获取该beanName对应的BeanDefinition实例,从上面说到的beanDefinitionMap表中查找 33            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 34            checkMergedBeanDefinition(mbd, beanName, args); 35            //判断是否有依赖bean 36            String[] dependsOn = mbd.getDependsOn(); 37            if (dependsOn != null) { 38                for (String dependsOnBean : dependsOn) { 39                    getBean(dependsOnBean);//如果有依赖bean,递归调用getBean方法 40                    registerDependentBean(dependsOnBean, beanName);//将依赖关系保存到 上面提到的 41                    //dependBeanMap和dependencyForBeanMap中。 42                } 43            } 44            // 真正的开始床架bean实例了。激动吧 45            if (mbd.isSingleton()) {//beanDefinition中指定该实例为单例 46                //去工厂中获取单例,如果没有创建一个,然后添加到工厂中,否则直接返回 47                sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { 48                    public Object getObject() throws BeansException { 49                        try { 50                            return createBean(beanName, mbd, args); 51                        } 52                    } 53                }); 54                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 55            } 56            else if (mbd.isPrototype()) {//原型方式,每次都创建一个新的实例 57                Object prototypeInstance = null; 58                try { 59                    beforePrototypeCreation(beanName); 60                    prototypeInstance = createBean(beanName, mbd, args); 61                } 62                finally { 63                    afterPrototypeCreation(beanName); 64                } 65                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); 66            } 67            else {//其他方式,如目前主体无关,不赘述 68            } 69        } 70        return (T) bean; 71    }

   这个方法好长,真的好长,我还删除了一些与当前主体无关的代码呢,好吧,不要被吓住,如果是自己写的代码,再长都很容易弄懂,类的继承关系再复杂都能轻车熟路,那是因为我们都清楚的知道每一行的用意,看别人的代码一样,多看几遍就明白了,再复杂都一样。

首先Spring会检查beanName,获取规范的beanName,然后它会检查是否存在已经注册的单例(查询上面提到的singletonObjects映射表),如果有的话就直接返回了,一切就结束了,否则的话,会查看是否存在父工厂,如果有调用父工厂的getBean方法,如果没有呢?

好吧那就要着手创建实例了,首先查看beanDefinitionMap查找该beanName对应的beanDefinition实例,然后根据该实例判断是否存在依赖关系,如果存在在递归的调用getBean方法,直到所有的依赖关系都正确的实例化和装配完成,并且将这些依赖关系保存到上面提到的dependencyForBeanMap 和dependentBeanMap中。

接下来,Spring查看BeanDefinition来确定该Bean应该是单例方式创建还是原型方式创建?如果是单例的话,Spring会调用getSingleton方法查找或创建一个单例(下面会详聊),如果是原型的话,每次调用getBean方法都会创建一个新的实例,看上面代码便会一清二楚了。

那下面我们就看看这个getSingleton方法做了什么?

1public Object getSingleton(String beanName, ObjectFactory singletonFactory) { 2        //这不就是上面说的bean实例映射表吗?哈,被同步了,保证线程安全啊 3        synchronized (this.singletonObjects) { 4            Object singletonObject = this.singletonObjects.get(beanName); 5            if (singletonObject == null) {//第一次创建当然是空 6                beforeSingletonCreation(beanName);//这个是看看当前的beanName是否在排除列表中,如果是 7                //则抛出异常 8                boolean recordSuppressedExceptions = (this.suppressedExceptions == null); 9                try {//这里调用了上面的匿名内部类的getObject方法了,实则调用了createBean方法 10                    singletonObject = singletonFactory.getObject(); 11                }//这不,添加到了singleObjects映射表中了,以备下次使用 12                addSingleton(beanName, singletonObject); 13            } 14            return (singletonObject != NULL_OBJECT ? singletonObject : null); 15        } 16    }

   这里稍微清晰了,查看singletonObjects映射表,看是否存在已经注册的单例,如果没有调用createBean方法创建一个,并且注册到singletonObjects映射表中,否则直接返回就Ok了。

下面就是createBean了, we are close。

1protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd,  2                                                                    final Object[] args) { 3        // Instantiate the bean. 4        BeanWrapper instanceWrapper = null; 5        if (mbd.isSingleton()) { 6            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); 7        } 8        if (instanceWrapper == null) {//实例化动作 9            instanceWrapper = createBeanInstance(beanName, mbd, args); 10        } 11        //.....some codes we don't care. 12        //...... 13        // Initialize the bean instance. 14        Object exposedObject = bean; 15        try {/////装配动作 16            populateBean(beanName, mbd, instanceWrapper); 17            if (exposedObject != null) {//后面会讲到,暂时不关心 18                exposedObject = initializeBean(beanName, exposedObject, mbd); 19            } 20        } 21        //........some codes we don't care. 22        return exposedObject; 23    }

   比较清晰(同样去除了一些我们不关心的代码),上面的方法分了我们期望的两部执行,第一实例化Bean,第二装配Bean。

第一步实例化主要是通过确定调用的构造器来最终调用Class.newInstance(args)方法来实例化Bean。不做细究,有兴趣可以自己看看,比较简单,主要是第二部装配,也就是处理我们的@Autowired注解(终于找到正题了)。

六、执行装配

    方法populateBean执行了最终的Autowired动作,我们看一下它做了什么?话说这块有点麻烦了,开始之前想讲几个比较重要的类和接口吧:

A) PropertyValue:这是一个用来表示Bean属性的对象,其中定义了属性的名字和值等信息,如simpleService,和simpleDao属性。

B) PropertyDescriptor:这个事Bean属性的描述符,其中定义了该属性可能存在的setter和getter方法,以及所有Bean的Class对象。

C) InjectionMetadata:这个是注入元数据,包含了目标Bean的Class对象,和注入元素(InjectionElement)集合.

D) InjectionElement:这个是注入元素,包含了注入元素的java.lang.reflect.Member 的对象,以及一个PropertyDescriptor对象。就是对java.lang.reflect.Member的一个封装,用来执行最终的注入动作,它有两个子类,分别是:AutowiredFieldElement表示字段属性,AutowiredMethodElement表示方法。

其实最终的目标就是将PropertyValue中的value值赋给InjectionElement中的Member对象。那它是怎么做的呢?

1protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) { 2        //尝试从BeanDefinition中获取PropertyValue的属性集合,很明显没有值呢还。 3        PropertyValues pvs = mbd.getPropertyValues(); 4        //.....其中执行了一些BeanPostProcessor的postProcessAfterInstantiation动作,我们不关心。 5        //.....移除了 6 7        //这里比较重要,这里会设置上面的PropertyValues的值,默认情况下是getResolvedAutowiredMode方法返回 8        //0, 但是我们可以在xml配置文件中设置<beans/>标签的default-autowire属性来改变它。 9        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || 10                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { 11            MutablePropertyValues newPvs = new MutablePropertyValues(pvs); 12            // Add property values based on autowire by name if applicable. 13            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { 14                autowireByName(beanName, mbd, bw, newPvs); 15            } 16            // Add property values based on autowire by type if applicable. 17            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { 18                autowireByType(beanName, mbd, bw, newPvs); 19            } 20            pvs = newPvs; 21        } 22        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); 23        boolean needsDepCheck = (mbd.getDependencyCheck() !=  24                                                RootBeanDefinition.DEPENDENCY_CHECK_NONE); 25        if (hasInstAwareBpps || needsDepCheck) { 26            PropertyDescriptor[] filteredPds =  27                            filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); 28            if (hasInstAwareBpps) { 29                //这里便是最最最重要的了,也就是最终的Autowired了。 30                for (BeanPostProcessor bp : getBeanPostProcessors()) { 31                    if (bp instanceof InstantiationAwareBeanPostProcessor) { 32                        InstantiationAwareBeanPostProcessor ibp =  33                                                    (InstantiationAwareBeanPostProcessor) bp; 34                        pvs = ibp.postProcessPropertyValues(//瞅到没,这个方法哦~~~ 35                                        pvs, filteredPds, bw.getWrappedInstance(), beanName); 36                        if (pvs == null) { 37                            return; 38                        } 39                    } 40                } 41            } 42            if (needsDepCheck) { 43                checkDependencies(beanName, mbd, filteredPds, pvs); 44            } 45        } 46        applyPropertyValues(beanName, mbd, bw, pvs); 47    }

   Spring 尝试获取bean definition的PropertyValue集合,开始当然是空的,然后下面便是进行根据名字或者类型为我们的PropertyValue集合进行赋值了, 在不设置<beans default-autowire="byName/byType"/>的情况下是不会调用这个方法的,如果设置了byName,我们来看看做了什么?

1protected void autowireByName( 2            String beanName, AbstractBeanDefinition mbd,  3            BeanWrapper bw, MutablePropertyValues pvs) { 4        //找到还没赋值的属性名称,看下面方法 5        String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); 6        for (String propertyName : propertyNames) { 7            if (containsBean(propertyName)) { 8                //递归调用getBean,如果没有创建并注册,有了直接返回。 9                Object bean = getBean(propertyName); 10                //将刚得到或创建的bean赋值给PropertyValue 11                pvs.add(propertyName, bean); 12                //并将该属性名和实例注册到依赖关系映射表dependentBeanMap和dependencyForBeanMap中 13                registerDependentBean(propertyName, beanName); 14            } 15        } 16    } 17 18protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) { 19        Set<String> result = new TreeSet<String>(); 20        PropertyValues pvs = mbd.getPropertyValues(); 21        PropertyDescriptor[] pds = bw.getPropertyDescriptors(); 22        //遍历bean的所有属性,并将符合条件的属性名添加到结果列表中 23        for (PropertyDescriptor pd : pds) { 24            if (pd.getWriteMethod() != null  25                && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) && 26                    !BeanUtils.isSimpleProperty(pd.getPropertyType())) { 27                result.add(pd.getName()); 28            } 29        } 30        return StringUtils.toStringArray(result); 31    }

   上面两段代码的意思是,查看当前bean的所有属性(描述符),然后依次判断查找符合条件的属性,并添加到属性名称数组中,然后遍历这个数组,对其中的属性名依次调用getBean(propertyName)方法来获取或创建该名称的bean实例,并将该bean实例设为PropertyValue的value值,最后添加到依赖关系映射表中(dependencyForBeanMap和dependentBeanMap)。好了此时PropertyValues有值了,后面就可以用它来注入到bean的属性中了。我们接着看上面populateBean方法。

PropertyValue值设置后,Spring会调用getBeanPostProcessor方法遍历Bean工厂中注册的所有BeanPostProcessor,其中就包括AutowiredAnnotationBeanPostProcessor(这些BeanPostProcessor都是系统默认硬编码注册到bean工厂中的)。接着就会调用AutowiredAnnotationBeanPostProcessor的postProcessPropertyValues方法,并将之前的PropertyValues和bean实例传递进去。

1//虽然PropertyValues属性传递过去了,但是并没有使用它直接赋值给属性变量(还不清楚为什么会传递它,其实没用到) 2@Override 3public PropertyValues postProcessPropertyValues(PropertyValues pvs,  4                PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { 5        //调用下面的方法获取InjectionMetadata对象(其实InjectionElement集合) 6        InjectionMetadata metadata = findAutowiringMetadata(bean.getClass()); 7        try { 8            metadata.inject(bean, beanName, pvs); 9        } 10        return pvs; 11    } 12 13private InjectionMetadata findAutowiringMetadata(Class<?> clazz) { 14        // 先找缓存 15        InjectionMetadata metadata = this.injectionMetadataCache.get(clazz); 16        if (metadata == null) { 17            synchronized (this.injectionMetadataCache) { 18                metadata = this.injectionMetadataCache.get(clazz); 19                if (metadata == null) { 20                    //缓存没有,调用buildAutowiringMetadata方法构建 21                    metadata = buildAutowiringMetadata(clazz); 22                    this.injectionMetadataCache.put(clazz, metadata); 23                } 24            } 25        } 26        return metadata; 27    } 28 29private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) { 30        LinkedList<InjectionMetadata.InjectedElement> elements =  31                                        new LinkedList<InjectionMetadata.InjectedElement>(); 32        Class<?> targetClass = clazz; 33        do {//这里一个循环,因为要考虑父类的字段和方法 34            LinkedList<InjectionMetadata.InjectedElement> currElements =  35                                    new LinkedList<InjectionMetadata.InjectedElement>(); 36            for (Field field : targetClass.getDeclaredFields()) { 37                //遍历每一个field,找到被标记为@Autowired的field 38                Annotation annotation = findAutowiredAnnotation(field); 39                if (annotation != null) { 40                    if (Modifier.isStatic(field.getModifiers())) { 41                        continue;//不可一世static的。 42                    } 43                    boolean required = determineRequiredStatus(annotation); 44                    //创建AutowiredFieldElement。 45                    currElements.add(new AutowiredFieldElement(field, required)); 46                } 47            } 48            for (Method method : targetClass.getDeclaredMethods()) { 49                //遍历所有方法,这里有个桥方法的处理,我们不关心 50                Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); 51                Annotation annotation = BridgeMethodResolver 52                                    .isVisibilityBridgeMethodPair(method, bridgedMethod) ? 53                                        findAutowiredAnnotation(bridgedMethod) : 54                                     findAutowiredAnnotation(method); 55                if (annotation != null &&  56                            method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { 57                    if (Modifier.isStatic(method.getModifiers())) { 58                        continue; 59                    } 60                    if (method.getParameterTypes().length == 0) { 61                    } 62                    boolean required = determineRequiredStatus(annotation); 63                    PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method); 64                    //创建AutowiredMethodElement。 65                    currElements.add(new AutowiredMethodElement(method, required, pd)); 66                } 67            } 68            elements.addAll(0, currElements); 69            targetClass = targetClass.getSuperclass(); 70        } 71        while (targetClass != null && targetClass != Object.class); 72        //将InjectionElement集合添加到新建的InjectionMetadata中。 73        return new InjectionMetadata(clazz, elements); 74    }

   上面三个方法看似复杂其实很简单,首先Spring尝试调用findAutowiringMetadata方法获取该bean的InjectionMetadata实例(也就是有哪些属性需要被自动装配,也就是查找被@Autowired注解标记的元素)。怎么获取呢?首先去缓存里面找,找不到就遍历bean的和父类的字段域和方法,如果别标记为@Autowired并且不是静态的就添加到InjectionMetadata中,并添加到缓存中(各种缓存啊)。获得InjectionMetadata对象后便遍历其中的所有InjectionElement对象,调用其中的inject方法。前面说了InjectionElement有两个实现类,我们只看一个就可以,因为基本相同:

1@Override 2        protected void inject(Object bean, String beanName, PropertyValues pvs)  3                                                            throws Throwable { 4            Field field = (Field) this.member; 5            try { 6                Object value; 7                if (this.cached) { 8                    value = resolvedCachedArgument(beanName, this.cachedFieldValue); 9                } 10                else { 11                    DependencyDescriptor descriptor  12                                        = new DependencyDescriptor(field, this.required); 13                    Set<String> autowiredBeanNames = new LinkedHashSet<String>(1); 14                    TypeConverter typeConverter = beanFactory.getTypeConverter(); 15                    //这里是重中之重,获取真正的属性值。 16                    value = beanFactory.resolveDependency(descriptor, beanName,  17                                                autowiredBeanNames, typeConverter); 18                } 19                if (value != null) { 20                    ReflectionUtils.makeAccessible(field); 21                    field.set(bean, value);//最终赋值结束。 22                } 23            } 24        } 25    }

  可以看到,虽然PropertyValues属性传递过去了,但是并没有使用它直接赋值给属性变量(还不清楚为什么会传递它,其实没用到),而是通过调用bean工厂的resolveDependency方法来获取属性值得。那我们看一下resolveDependency做了什么?

1protected Object doResolveDependency(DependencyDescriptor descriptor,  2                                        Class<?> type, String beanName, 3                                     Set<String> autowiredBeanNames,  4                                TypeConverter typeConverter) throws BeansException  { 5        if (type.isArray()) {//如果属性类型是数组 6            Class<?> componentType = type.getComponentType(); 7            Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, descriptor); 8            if (autowiredBeanNames != null) { 9                autowiredBeanNames.addAll(matchingBeans.keySet()); 10            } 11            TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); 12            return converter.convertIfNecessary(matchingBeans.values(), type); 13        }//如果属性是集合,并且是接口 14        else if (Collection.class.isAssignableFrom(type) && type.isInterface()) { 15            Class<?> elementType = descriptor.getCollectionType(); 16            Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, descriptor); 17            if (autowiredBeanNames != null) { 18                autowiredBeanNames.addAll(matchingBeans.keySet()); 19            } 20            TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); 21            return converter.convertIfNecessary(matchingBeans.values(), type); 22        }//如果属性是Map并且是接口 23        else if (Map.class.isAssignableFrom(type) && type.isInterface()) { 24            Class<?> keyType = descriptor.getMapKeyType(); 25            Class<?> valueType = descriptor.getMapValueType(); 26            Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, descriptor); 27            if (autowiredBeanNames != null) { 28                autowiredBeanNames.addAll(matchingBeans.keySet()); 29            } 30            return matchingBeans; 31        }//自定义类型了 32        else {//都调用了这个方法 33            Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); 34            if (matchingBeans.size() > 1) { 35                String primaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor); 36                if (autowiredBeanNames != null) { 37                    autowiredBeanNames.add(primaryBeanName); 38                } 39                return matchingBeans.get(primaryBeanName); 40            } 41            // We have exactly one match. 42            Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next(); 43            if (autowiredBeanNames != null) { 44                autowiredBeanNames.add(entry.getKey()); 45            } 46            return entry.getValue(); 47        } 48    }

   这个方法其实就是根据类型到bean工厂中查找类型匹配的bean实例,然后就看到了这几个条件分支语句,如果是数组,集合,映射表,自定义类型都执行了差不多的操作,findAutowireCandidate方法。这个方法会去工厂中执行类型匹配的查找,将匹配的结果集返回,不同的是,集合数组类型会通过TypeConverter进行结果的转换。

到此为止,找到了属性的匹配值,然后反射赋值就完成了整个的自动装配过程。可以看出,@Autowired是通过类型来进行自动装配的。

上面是属性的赋值过程也就是InjectionFieldElement的inject方法,InjectionMethodElement的inject方法大致相同只是对每一个方法参数执行一次resolveDependency方法来获取参数值,然后反射执行方法。

到此为止,整个实例化和装配过程也就讲完了,我们总结一下:

1)一切都是从bean工厂的getBean方法开始的,一旦该方法调用总会返回一个bean实例,无论当前是否存在,不存在就实例化一个并装配,否则直接返回。

2)实例化和装配过程中会多次递归调用getBean方法来解决类之间的依赖。

3)Spring几乎考虑了所有可能性,所以方法特别复杂但完整有条理。

4)@Autowired最终是根据类型来查找和装配元素的,但是我们设置了<beans default-autowire="byName"/>后会影响最终的类型匹配查找。因为在前面有根据BeanDefinition的autowire类型设置PropertyValue值得一步,其中会有新实例的创建和注册。就是那个autowireByName方法。

七、一切的开始

    我们上面讲完了整个Autowire过程了。那么,还有一个问题,上一篇我们知道了什么时候执行的配置文件读取和组件扫描,但Spring MVC是在什么时候开始执行真个实例化过程的呢?很简单就在组件扫描完成之后,bean工厂的refresh方法中(还记得吗?)

1public void refresh() throws BeansException, IllegalStateException { 2        synchronized (this.startupShutdownMonitor) { 3            prepareRefresh(); 4            //前面说过,这里面执行了,组件扫描和配置文件读取 5            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 6            prepareBeanFactory(beanFactory); 7            try { 8                postProcessBeanFactory(beanFactory); 9                invokeBeanFactoryPostProcessors(beanFactory); 10                //这里注册了BeanPostProcessor,包括AutowiredAnnotationBeanPostProcessor 11                registerBeanPostProcessors(beanFactory); 12                initMessageSource(); 13                initApplicationEventMulticaster(); 14                onRefresh(); 15                registerListeners(); 16                //这里就执行了所有非延迟加载的实例化工作。//here 17                finishBeanFactoryInitialization(beanFactory); 18                finishRefresh(); 19            } 20        } 21    }

   就是上面的finishBeanFactoryInitialization方法执行了装配工作,该方法会调用bean工厂的preInstantiateSingletons方法,这个方法会遍历所有注册的bean definition实例,如果是单例并且是非延迟加载的就调用getBean方法。

好了,到此为止我们就清晰的了解了,Spring MVC的实例化和自动装配工作了,如有问题欢迎评论中提出,我们一起讨论。

累死了~~~~~~~

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )