1、Spring源码分析注解Spring源码分析注解1.类内部的注解,如:Autowire、Value、Required、Resource以及EJB和WebSerivce相关的注解,是容器对Bean对象实例化和依赖注入时,通过容器中注册的Bean后置处理器处理这些注解的。2.Spring中处理注解的Bean后置处理器:当使用Spring的注解功能时,在Spring配置文件中添加如下配置开启Spring的注解处理器:xhtml view plaincopy1 2 上面的配置将隐式地向Spring容器注册、CommonAnnotationBeanPostProcessor、PersistenceAnn
2、otationBeanPostProcessor以及这4个专门用于处理注解的Bean后置处理器。下面将具体介绍这4个注解后置处理器。:是Spring容器专门处理配置了自动依赖注入装配相关注解(Autowire、Value以及其他JSR-330注解)的Bean后置处理器,其主要功能源码如下:(1).的构造方法:AutowiredAnnotationBeanPostProcessor只有一个的构造方法,其源码如下:java view plaincopy3 public AutowiredAnnotationBeanPostProcessor() 4 /后置处理器将处理Autowire注解 5 th
3、is.autowiredAnnotationTypes.add(Autowired.class); 6 /后置处理器将处理Value注解 7 this.autowiredAnnotationTypes.add(Value.class); 8 /获取当前类的类加载器 9 ClassLoader cl = AutowiredAnnotationBeanPostProcessor.class.getClassLoader(); 10 try 11 /后置处理器将处理javax.inject.Inject JSR-330注解 12 this.autowiredAnnotationTypes.add(C
4、lass) cl.loadClass(javax.inject.Inject); 13 logger.info(JSR-330 javax.inject.Inject annotation found and supported for autowiring); 14 15 catch (ClassNotFoundException ex) 16 / JSR-330 API not available - simply skip. 17 18 (2).为指定类选择其合适的构造方法:容器对指定类进行自动依赖注入装配(autowiring)时,容器需要对Bean调用合适的构造方法创建实例对象,Au
5、towiredAnnotationBeanPostProcessor为指定类选择相应的构造方法,源码如下:java view plaincopy19 /为自动依赖注入装配Bean选择合适的构造方法 20 public Constructor determineCandidateConstructors(Class beanClass, String beanName) throws BeansException 21 /首先从容器的缓存中查找是否有指定Bean的构造方法 22 Constructor candidateConstructors = this.candidateConstruct
6、orsCache.get(beanClass); 23 /容器缓存中没有给定类的构造方法 24 if (candidateConstructors = null) 25 /线程同步以确保容器中数据一致性 26 synchronized (this.candidateConstructorsCache) 27 candidateConstructors = this.candidateConstructorsCache.get(beanClass); 28 if (candidateConstructors = null) 29 /通过JDK反射机制,获取指定类的中所有声明的构造方法 30 Co
7、nstructor rawCandidates = beanClass.getDeclaredConstructors(); 31 /存放候选构造方法的集合 32 List candidates = new ArrayList(rawCandidates.length); 33 /autowire注解中required属性指定的构造方法 34 Constructor requiredConstructor = null; 35 /默认的构造方法 36 Constructor defaultConstructor = null; 37 /遍历所有的构造方法,检查是否添加了autowire注解,以
8、及是否 38 /指定了required属性 39 for (Constructor candidate : rawCandidates) 40 /获取指定类中所有关于autowire的注解(Annotation) 41 Annotation annotation = findAutowiredAnnotation(candidate); 42 /如果指定类中有关于antowire的注解 43 if (annotation != null) 44 /如果antowire注解中指定了required属性 45 if (requiredConstructor != null) 46 throw ne
9、w BeanCreationException(Invalid autowire-marked constructor: + candidate + 47 . Found another constructor with required Autowired annotation: + 48 requiredConstructor); 49 50 /如果autowire注解的参数列表为空 51 if (candidate.getParameterTypes().length = 0) 52 throw new IllegalStateException( 53 Autowired annota
10、tion requires at least one argument: + candidate); 54 55 /获取autowire注解中required属性值 56 boolean required = determineRequiredStatus(annotation); 57 /如果获取到autowire注解中required的属性值 58 if (required) 59 /如果候选构造方法集合不为空 60 if (!candidates.isEmpty() 61 throw new BeanCreationException( 62 Invalid autowire-marke
11、d constructors: + candidates + 63 . Found another constructor with required Autowired annotation: + 64 requiredConstructor); 65 66 /当前的构造方法就是required属性所配置的构造方法 67 requiredConstructor = candidate; 68 69 /将当前的构造方法添加到哦啊候选构造方法集合中 70 candidates.add(candidate); 71 72 /如果类中没有autowire的相关注解,并且构造方法参数列表为空 73 e
12、lse if (candidate.getParameterTypes().length = 0) 74 /当前的构造方法是默认构造方法 75 defaultConstructor = candidate; 76 77 78 /如果候选构造方法集合不为空 79 if (!candidates.isEmpty() 80 /如果所有的构造方法都没有配置required属性,且有默认构造方法 81 if (requiredConstructor = null & defaultConstructor != null) 82 /将默认构造方法添加到候选构造方法列表 83 candidates.add(
13、defaultConstructor); 84 85 /将候选构造方法集合转换为数组 86 candidateConstructors = candidates.toArray(new Constructorcandidates.size(); 87 88 /如果候选构造方法集合为空,则创建一个空的数组 89 else 90 candidateConstructors = new Constructor0; 91 92 /将类的候选构造方法集合存放到容器的缓存中 93 this.candidateConstructorsCache.put(beanClass, candidateConstru
14、ctors); 94 95 96 97 /返回指定类的候选构造方法数组,如果没有返回null 98 return (candidateConstructors.length 0 ? candidateConstructors : null); 99 (3).AutowiredAnnotationBeanPostProcessor对方法和属性的依赖注入:当Spring容器对配置了autowire相关注解的Bean进行依赖注入时,后置处理器对属性和对象进行自动注入处理,源码如下:java view plaincopy100 /处理类中的属性 101 public PropertyValues po
15、stProcessPropertyValues( 102 PropertyValues pvs, PropertyDescriptor pds, Object bean, String beanName) throws BeansException 103 /获取指定类中autowire相关注解的元信息 104 InjectionMetadata metadata = findAutowiringMetadata(bean.getClass(); 105 try 106 /对Bean的属性进行自动注入 107 metadata.inject(bean, beanName, pvs); 108
16、109 catch (Throwable ex) 110 throw new BeanCreationException(beanName, Injection of autowired dependencies failed, ex); 111 112 return pvs; 113 114 /处理对象的注入 115 public void processInjection(Object bean) throws BeansException 116 /获取给定Bean的Class对象 117 Class clazz = bean.getClass(); 118 /获取给定类中autowir
17、e相关注解元信息 119 InjectionMetadata metadata = findAutowiringMetadata(clazz); 120 try 121 /对Bean对象进行自动注入 122 metadata.inject(bean, null, null); 123 124 catch (Throwable ex) 125 throw new BeanCreationException(Injection of autowired dependencies failed for class + clazz + , ex); 126 127 128 /获取给定类的autowir
18、e相关注解元信息 129 private InjectionMetadata findAutowiringMetadata(Class clazz) 130 /首先从容器中查找是否有给定类的autowire相关注解元信息 131 InjectionMetadata metadata = this.injectionMetadataCache.get(clazz); 132 if (metadata = null) 133 synchronized (this.injectionMetadataCache) 134 metadata = this.injectionMetadataCache.g
19、et(clazz); 135 if (metadata = null) 136 /解析给定类autowire相关注解元信息 137 metadata = buildAutowiringMetadata(clazz); 138 /将得到的给定类autowire相关注解元信息存储在容器缓存中 139 this.injectionMetadataCache.put(clazz, metadata); 140 141 142 143 return metadata; 144 145 /解析给定类autowire相关注解元信息 146 private InjectionMetadata buildAut
20、owiringMetadata(Class clazz) 147 /创建一个存放注解元信息的集合 148 LinkedList elements = new LinkedList(); 149 Class targetClass = clazz; 150 /递归遍历当前类及其所有基类,解析全部注解元信息 151 do 152 /创建一个存储当前正在处理类注解元信息的集合 153 LinkedList currElements = new LinkedList(); 154 /利用JDK反射机制获取给定类中所有的声明字段,获取字段上的注解信息 155 for (Field field : tar
21、getClass.getDeclaredFields() 156 /获取给定字段上的注解 157 Annotation annotation = findAutowiredAnnotation(field); 158 if (annotation != null) 159 /如果给定字段是静态的(Static),则直接遍历下一个字段 if (Modifier.isStatic(field.getModifiers() 160 if (logger.isWarnEnabled() 161 logger.warn(Autowired annotation is not supported on s
22、tatic fields: + field); 162 163 continue; 164 165 /判断注解的required属性值是否有效 166 boolean required = determineRequiredStatus(annotation); 167 /将当前字段元信息封装,添加在返回的集合中 168 currElements.add(new AutowiredFieldElement(field, required); 169 170 171 /利用JDK反射机制获取给定类中所有的声明方法,获取方法上的注解信息 172 for (Method method : targe
23、tClass.getDeclaredMethods() 173 /获取给定方法上的所有注解 174 Annotation annotation = findAutowiredAnnotation(method); 175 if (annotation != null & method.equals(ClassUtils.getMostSpecificMethod(method, clazz) 176 /如果方法是静态的,则直接遍历下一个方法 177 if (Modifier.isStatic(method.getModifiers() 178 if (logger.isWarnEnabled(
24、) 179 logger.warn(Autowired annotation is not supported on static methods: + method); 180 181 continue; 182 183 /如果方法的参数列表为空 184 if (method.getParameterTypes().length = 0) 185 if (logger.isWarnEnabled() 186 logger.warn(Autowired annotation should be used on methods with actual parameters: + method);
25、 187 188 189 /判断注解的required属性值是否有效 190 boolean required = determineRequiredStatus(annotation); 191 /获取当前方法的属性描述符,即方法是可读的(readable)getter方法, 192 /还是可写的(writeable)setter方法 193 PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method); 194 /将方法元信息封装添加到返回的元信息集合中 195 currElements.add(new AutowiredM
26、ethodElement(method, required, pd); 196 197 198 /将当前类的注解元信息存放到注解元信息集合中 199 elements.addAll(0, currElements); 200 /获取给定类的父类 201 targetClass = targetClass.getSuperclass(); 202 203 /如果给定类有基类,并且基类不是Object,则递归获取其基类的元信息 204 while (targetClass != null & targetClass != Object.class); 205 return new Injectio
27、nMetadata(clazz, elements); 206 207 /获取给定对象的autowire相关注解 208 private Annotation findAutowiredAnnotation(AccessibleObject ao) 209 /遍历所有autowire相关的注解:Autowire、Value以及JSR-330等 210 for (Class type : this.autowiredAnnotationTypes) 211 /获取给定对象上的指定类型的注解 212 Annotation annotation = ao.getAnnotation(type); 2
28、13 if (annotation != null) 214 return annotation; 215 216 217 return null; 218 (4).AutowiredAnnotationBeanPostProcessor对字段和方法的注入:a.AutowiredAnnotationBeanPostProcessor对字段的注入是通过AutowiredFieldElement类的inject方法实现的,源码如下:java view plaincopy219 /对字段进行注入 220 protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable 221 /获取注入元素对象 222 Field field = (Field) this.member; 223 try 224 Object value; 225 /如果当前对象在容器中被缓存 226 if (this.cached) 227 /根据Bean名称解析缓存中的字段值 228 value = resolvedCachedArgument(beanName, this.cached
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1