springMVC常用注解解读

2 篇文章 0 订阅

Spring MVC 解读——@Autowired

一、@Autowired

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

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

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

二、BeanPostProcessor

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

[java]  view plain  copy
  1. <pre name="code" class="java">Note that actual injection is performed through a BeanPostProcessor   
  2. which in turn means that you cannot use @Autowired to inject references into BeanPostProcessor  
  3. or BeanFactoryPostProcessor types.   
  4. Please 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实现类完成。那我们不妨看一下他们的定义:

?
 
[java]  view plain  copy
  1. public interface BeanPostProcessor {  
  2.     Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;  
  3.     Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;  
  4. }  

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


 

[java]  view plain  copy
  1. BeanPostProcessor implementation that autowires annotated fields, setter methods and arbitrary   
  2. config methods. Such members to be injected are detected through a Java 5 annotation:   
  3. by default, Spring's @Autowired and @Value annotations.Also supports JSR-330'@Inject   
  4. annotation, if available, as a direct alternative to Spring's own @Autowired.  
  5.    
  6. Note: A default AutowiredAnnotationBeanPostProcessor will be registered by   
  7. the "context:annotation-config" and "context:component-scan" XML tags.  
  8.    
  9. NOTE: Annotation injection will be performed before XML   
  10. injection; thus the latter configuration will override the former for properties   
  11. wired 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实例执行了自动装配,那么它做了什么呢?

三、磨刀砍柴    

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


[java]  view plain  copy
  1. //==================================Controller  
  2. @Controller  
  3. public class SimpleController {  
  4.     @Autowired  
  5.     private SimpleService simpleService;  
  6. }  
  7. //==================================Service  
  8. @Service("simpleService")  
  9. public class SimpleServiceImpl implements SimpleService {  
  10.     @Autowired  
  11.     private SimpleDao simpleDao;  
  12. }  
  13. //===================================Repository  
  14. @Repository("simpleDao")  
  15. public 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工厂中的属性和方法:

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

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

五,实例化与装配

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


[java]  view plain  copy
  1. public Object getBean(String name) throws BeansException {  
  2.     return doGetBean(name, nullnullfalse);  
  3. }  
  4.    
  5. @SuppressWarnings("unchecked")  
  6. protected <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方法做了什么?

?
6
[java]  view plain  copy
  1. public 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。

?
 
[java]  view plain  copy
  1. protected 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对象。那它是怎么做的呢?


 
[java]  view plain  copy
  1. protected 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,我们来看看做了什么?

?
[java]  view plain  copy
  1. protected 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.    
  18. protected 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实例传递进去。

?
[java]  view plain  copy
  1. //虽然PropertyValues属性传递过去了,但是并没有使用它直接赋值给属性变量(还不清楚为什么会传递它,其实没用到)  
  2. @Override  
  3. public 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.    
  13. private 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.    
  29. private 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有两个实现类,我们只看一个就可以,因为基本相同:

?
[java]  view plain  copy
  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做了什么?

?
[java]  view plain  copy
  1. protected 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方法中(还记得吗?)

?
 
[java]  view plain  copy
  1. public 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的实例化和自动装配工作了,如有问题欢迎评论中提出,我们一起讨论。


转:http://my.oschina.net/HeliosFly/blog/203902

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值