7 编码剖析@Resource注解的实现原理
七 编码剖析@Resource注解的实现原理
七 编码剖析@Resource注解的实现原理 ItcastResource.java view plaincopy to clipboardprint? 01.package junit.test; 02. 03.import java.lang.annotation.ElementType; 04.import java.lang.annotation.Retention; 05.import java.lang.annotation.RetentionPolicy; 06.import java.lang.annotation.Target; 07. 08.@Retention(RetentionPolicy.RUNTIME) 09.@Target({ElementType.FIELD, ElementType.METHOD}) 10.public @interface ItcastResource { 11. public String name() default ""; 12.} package junit.test; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD}) public @interface ItcastResource { public String name() default ""; } PropertyDefinition .java view plaincopy to clipboardprint? 01.package junit.test; 02. 03.public class PropertyDefinition { 04. private String name; 05. private String ref; 06. private String value; 07. 08. public String getValue() { 09. return value; 10. } 11. 12. public void setValue(String value) { 13. this.value = value; 14. } 15. 16. public PropertyDefinition(String name, String ref, String value) { 17. this.name = name; 18. this.ref = ref; 19. this.value = value; 20. } 21. 22. public String getName() { 23. return name; 24. } 25. public void setName(String name) { 26. this.name = name; 27. } 28. public String getRef() { 29. return ref; 30. } 31. public void setRef(String ref) { 32. this.ref = ref; 33. } 34. 35.} package junit.test; public class PropertyDefinition { private String name; private String ref; private String value; public String getValue() { return value; } public void setValue(String value) { this.value = value; } public PropertyDefinition(String name, String ref, String value) { this.name = name; this.ref = ref; this.value = value; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getRef() { return ref; } public void setRef(String ref) { this.ref = ref; } } BeanDefinition.java view plaincopy to clipboardprint? 01.package junit.test; 02. 03.import java.util.ArrayList; 04.import java.util.List; 05. 06.public class BeanDefinition { 07. private String id; 08. private String className; 09. private List<PropertyDefinition> propertys = new ArrayList<PropertyDefinition>(); 10. 11. public BeanDefinition(String id, String className) { 12. this.id = id; 13. this.className = className; 14. } 15. public String getId() { 16. return id; 17. } 18. public void setId(String id) { 19. this.id = id; 20. } 21. public String getClassName() { 22. return className; 23. } 24. public void setClassName(String className) { 25. this.className = className; 26. } 27. public List<PropertyDefinition> getPropertys() { 28. return propertys; 29. } 30. public void setPropertys(List<PropertyDefinition> propertys) { 31. this.propertys = propertys; 32. } 33. 34.} package junit.test; import java.util.ArrayList; import java.util.List; public class BeanDefinition { private String id; private String className; private List<PropertyDefinition> propertys = new ArrayList<PropertyDefinition>(); public BeanDefinition(String id, String className) { this.id = id; this.className = className; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } public List<PropertyDefinition> getPropertys() { return propertys; } public void setPropertys(List<PropertyDefinition> propertys) { this.propertys = propertys; } } ItcastClassPathXMLApplicationContext.java view plaincopy to clipboardprint? 01.package junit.test; 02. 03.import java.beans.Introspector; 04.import java.beans.PropertyDescriptor; 05.import java.lang.reflect.Field; 06.import java.lang.reflect.Method; 07.import java.net.URL; 08.import java.util.ArrayList; 09.import java.util.HashMap; 10.import java.util.List; 11.import java.util.Map; 12. 13.import org.apache.commons.beanutils.ConvertUtils; 14.import org.dom4j.Document; 15.import org.dom4j.Element; 16.import org.dom4j.XPath; 17.import org.dom4j.io.SAXReader; 18. 19./** 20. * 传智传客版容器 21. * 22. */ 23.public class ItcastClassPathXMLApplicationContext { 24. private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>(); 25. private Map<String, Object> sigletons = new HashMap<String, Object>(); 26. 27. public ItcastClassPathXMLApplicationContext(String filename){ 28. this.readXML(filename); 29. this.instanceBeans(); 30. this.annotationInject(); 31. this.injectObject(); 32. } 33. /** 34. * 通过注解实现注入依赖对象 35. */ 36. private void annotationInject() { 37. for(String beanName : sigletons.keySet()){ 38. Object bean = sigletons.get(beanName); 39. if(bean!=null){ 40. try { 41. PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); 42. for(PropertyDescriptor properdesc : ps){ 43. Method setter = properdesc.getWriteMethod();//获取属性的setter方法 44. if(setter!=null && setter.isAnnotationPresent(ItcastResource.class)){ 45. ItcastResource resource = setter.getAnnotation(ItcastResource.class); 46. Object value = null; 47. if(resource.name()!=null && !"".equals(resource.name())){ 48. value = sigletons.get(resource.name()); 49. }else{ 50. value = sigletons.get(properdesc.getName()); 51. if(value==null){ 52. for(String key : sigletons.keySet()){ 53. if(properdesc.getPropertyType().isAssignableFrom(sigletons.get(key).getClass())){ 54. value = sigletons.get(key); 55. break; 56. } 57. } 58. } 59. } 60. setter.setAccessible(true); 61. setter.invoke(bean, value);//把引用对象注入到属性 62. } 63. } 64. Field[] fields = bean.getClass().getDeclaredFields(); 65. for(Field field : fields){ 66. if(field.isAnnotationPresent(ItcastResource.class)){ 67. ItcastResource resource = field.getAnnotation(ItcastResource.class); 68. Object value = null; 69. if(resource.name()!=null && !"".equals(resource.name())){ 70. value = sigletons.get(resource.name()); 71. }else{ 72. value = sigletons.get(field.getName()); 73. if(value==null){ 74. for(String key : sigletons.keySet()){ 75. if(field.getType().isAssignableFrom(sigletons.get(key).getClass())){ 76. value = sigletons.get(key); 77. break; 78. } 79. } 80. } 81. } 82. field.setAccessible(true);//允许访问private字段 83. field.set(bean, value); 84. } 85. } 86. } catch (Exception e) { 87. e.printStackTrace(); 88. } 89. } 90. } 91. } 92. 93. /** 94. * 为bean对象的属性注入值 95. */ 96. private void injectObject() { 97. for(BeanDefinition beanDefinition : beanDefines){ 98. Object bean = sigletons.get(beanDefinition.getId()); 99. if(bean!=null){ 100. try { 101. PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); 102. for(PropertyDefinition propertyDefinition : beanDefinition.getPropertys()){ 103. for(PropertyDescriptor properdesc : ps){ 104. if(propertyDefinition.getName().equals(properdesc.getName())){ 105. Method setter = properdesc.getWriteMethod();//获取属性的setter方法 ,private 106. if(setter!=null){ 107. Object value = null; 108. if(propertyDefinition.getRef()!=null && !"".equals(propertyDefinition.getRef().trim())){ 109. value = sigletons.get(propertyDefinition.getRef()); 110. }else{ 111. value = ConvertUtils.convert(propertyDefinition.getValue(), properdesc.getPropertyType()); 112. } 113. setter.setAccessible(true); 114. setter.invoke(bean, value);//把引用对象注入到属性 115. } 116. break; 117. } 118. } 119. } 120. } catch (Exception e) { 121. } 122. } 123. } 124. } 125. /** 126. * 完成bean的实例化 127. */ 128. private void instanceBeans() { 129. for(BeanDefinition beanDefinition : beanDefines){ 130. try { 131. if(beanDefinition.getClassName()!=null && !"".equals(beanDefinition.getClassName().trim())) 132. sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance()); 133. } catch (Exception e) { 134. e.printStackTrace(); 135. } 136. } 137. 138. } 139. /** 140. * 读取xml配置文件 141. * @param filename 142. */ 143. private void readXML(String filename) { 144. SAXReader saxReader = new SAXReader(); 145. Document document=null; 146. try{ 147. URL xmlpath = this.getClass().getClassLoader().getResource(filename); 148. document = saxReader.read(xmlpath); 149. Map<String,String> nsMap = new HashMap<String,String>(); 150. nsMap.put("ns","http://www.springframework.org/schema/beans");//加入命名空间 151. XPath xsub = document.createXPath("//ns:beans/ns:bean");//创建beans/bean查询路径 152. xsub.setNamespaceURIs(nsMap);//设置命名空间 153. List<Element> beans = xsub.selectNodes(document);//获取文档下所有bean节点 154. for(Element element: beans){ 155. String id = element.attributeValue("id");//获取id属性值 156. String clazz = element.attributeValue("class"); //获取class属性值 157. BeanDefinition beanDefine = new BeanDefinition(id, clazz); 158. XPath propertysub = element.createXPath("ns:property"); 159. propertysub.setNamespaceURIs(nsMap);//设置命名空间 160. List<Element> propertys = propertysub.selectNodes(element); 161. for(Element property : propertys){ 162. String propertyName = property.attributeValue("name"); 163. String propertyref = property.attributeValue("ref"); 164. String propertyValue = property.attributeValue("value"); 165. PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName, propertyref, propertyValue); 166. beanDefine.getPropertys().add(propertyDefinition); 167. } 168. beanDefines.add(beanDefine); 169. } 170. }catch(Exception e){ 171. e.printStackTrace(); 172. } 173. } 174. /** 175. * 获取bean实例 176. * @param beanName 177. * @return 178. */ 179. public Object getBean(String beanName){ 180. return this.sigletons.get(beanName); 181. } 182.} package junit.test; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.beanutils.ConvertUtils; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.XPath; import org.dom4j.io.SAXReader; /** * 传智传客版容器 * */ public class ItcastClassPathXMLApplicationContext { private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>(); private Map<String, Object> sigletons = new HashMap<String, Object>(); public ItcastClassPathXMLApplicationContext(String filename){ this.readXML(filename); this.instanceBeans(); this.annotationInject(); this.injectObject(); } /** * 通过注解实现注入依赖对象 */ private void annotationInject() { for(String beanName : sigletons.keySet()){ Object bean = sigletons.get(beanName); if(bean!=null){ try { PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); for(PropertyDescriptor properdesc : ps){ Method setter = properdesc.getWriteMethod();//获取属性的setter方法 if(setter!=null && setter.isAnnotationPresent(ItcastResource.class)){ ItcastResource resource = setter.getAnnotation(ItcastResource.class); Object value = null; if(resource.name()!=null && !"".equals(resource.name())){ value = sigletons.get(resource.name()); }else{ value = sigletons.get(properdesc.getName()); if(value==null){ for(String key : sigletons.keySet()){ if(properdesc.getPropertyType().isAssignableFrom(sigletons.get(key).getClass())){ value = sigletons.get(key); break; } } } } setter.setAccessible(true); setter.invoke(bean, value);//把引用对象注入到属性 } } Field[] fields = bean.getClass().getDeclaredFields(); for(Field field : fields){ if(field.isAnnotationPresent(ItcastResource.class)){ ItcastResource resource = field.getAnnotation(ItcastResource.class); Object value = null; if(resource.name()!=null && !"".equals(resource.name())){ value = sigletons.get(resource.name()); }else{ value = sigletons.get(field.getName()); if(value==null){ for(String key : sigletons.keySet()){ if(field.getType().isAssignableFrom(sigletons.get(key).getClass())){ value = sigletons.get(key); break; } } } } field.setAccessible(true);//允许访问private字段 field.set(bean, value); } } } catch (Exception e) { e.printStackTrace(); } } } } /** * 为bean对象的属性注入值 */ private void injectObject() { for(BeanDefinition beanDefinition : beanDefines){ Object bean = sigletons.get(beanDefinition.getId()); if(bean!=null){ try { PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); for(PropertyDefinition propertyDefinition : beanDefinition.getPropertys()){ for(PropertyDescriptor properdesc : ps){ if(propertyDefinition.getName().equals(properdesc.getName())){ Method setter = properdesc.getWriteMethod();//获取属性的setter方法 ,private if(setter!=null){ Object value = null; if(propertyDefinition.getRef()!=null && !"".equals(propertyDefinition.getRef().trim())){ value = sigletons.get(propertyDefinition.getRef()); }else{ value = ConvertUtils.convert(propertyDefinition.getValue(), properdesc.getPropertyType()); } setter.setAccessible(true); setter.invoke(bean, value);//把引用对象注入到属性 } break; } } } } catch (Exception e) { } } } } /** * 完成bean的实例化 */ private void instanceBeans() { for(BeanDefinition beanDefinition : beanDefines){ try { if(beanDefinition.getClassName()!=null && !"".equals(beanDefinition.getClassName().trim())) sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance()); } catch (Exception e) { e.printStackTrace(); } } } /** * 读取xml配置文件 * @param filename */ private void readXML(String filename) { SAXReader saxReader = new SAXReader(); Document document=null; try{ URL xmlpath = this.getClass().getClassLoader().getResource(filename); document = saxReader.read(xmlpath); Map<String,String> nsMap = new HashMap<String,String>(); nsMap.put("ns","http://www.springframework.org/schema/beans");//加入命名空间 XPath xsub = document.createXPath("//ns:beans/ns:bean");//创建beans/bean查询路径 xsub.setNamespaceURIs(nsMap);//设置命名空间 List<Element> beans = xsub.selectNodes(document);//获取文档下所有bean节点 for(Element element: beans){ String id = element.attributeValue("id");//获取id属性值 String clazz = element.attributeValue("class"); //获取class属性值 BeanDefinition beanDefine = new BeanDefinition(id, clazz); XPath propertysub = element.createXPath("ns:property"); propertysub.setNamespaceURIs(nsMap);//设置命名空间 List<Element> propertys = propertysub.selectNodes(element); for(Element property : propertys){ String propertyName = property.attributeValue("name"); String propertyref = property.attributeValue("ref"); String propertyValue = property.attributeValue("value"); PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName, propertyref, propertyValue); beanDefine.getPropertys().add(propertyDefinition); } beanDefines.add(beanDefine); } }catch(Exception e){ e.printStackTrace(); } } /** * 获取bean实例 * @param beanName * @return */ public Object getBean(String beanName){ return this.sigletons.get(beanName); } } 实际上也就是通过了反射技术来构造对象并且赋值,只是用到了注解的方法,并且利用@interface来构造自定义的注解类型。