首先分析。

1: 肯定要利用dom4j读取xml配置文件,将所有的bean的配置信息读取出来

2: 利用反射技术,实例化所有的bean

3: 写注解处理器, 利用注解和内省实现依赖对象的注入。

4: 利用XML中<property>信息,通过内省beanUtils实现基本数据类型的注入

实现:

  1. package cn.gbx.example;
  2.  
  3. import java.beans.IntrospectionException;
  4. import java.beans.Introspector;
  5. import java.beans.PropertyDescriptor;
  6. import java.io.File;
  7. import java.lang.reflect.Field;
  8. import java.lang.reflect.Method;
  9. import java.net.URL;
  10. import java.util.ArrayList;
  11. import java.util.HashMap;
  12. import java.util.List;
  13. import java.util.Map;
  14.  
  15. import org.apache.commons.beanutils.ConvertUtils;
  16. import org.dom4j.Document;
  17. import org.dom4j.Element;
  18. import org.dom4j.XPath;
  19. import org.dom4j.io.SAXReader;
  20. public class MyClassPathXmlApplicationContext {
  21. private List<DefBean> defBeans = new ArrayList<DefBean>();
  22. private Map<String, Object> singletons = new HashMap<String, Object>();
  23.  
  24. public MyClassPathXmlApplicationContext(String filename) {
  25. this.readXML(filename);
  26. this.instanceBean();
  27. this.injectAnotation();
  28. this.injectXML();
  29.  
  30. }
  31.  
  32. //注入基本类型的属性
  33. private void injectXML() {
  34. //枚举bean
  35. for (DefBean defBean : defBeans) {
  36. Object bean = singletons.get(defBean.getId());
  37. if (bean != null) {
  38. //枚举该bean的Property看有没有基本数据类型的注入
  39. for (DefProperty defProperty : defBean.getDefPropertys()) {
  40. if (defProperty.getValue() != null){
  41. try {
  42. PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
  43. for (PropertyDescriptor p : ps) {
  44. if (p.getName().equals(defProperty.getName())) {
  45. Method setter = p.getWriteMethod();
  46. //保证有set方法
  47. if (setter != null) {
  48. Object value = ConvertUtils.convert(defProperty.getValue(), p.getPropertyType());
  49. setter.setAccessible(true);
  50. setter.invoke(bean, value);
  51. }
  52. break;
  53. }
  54. }
  55. } catch (Exception e) {
  56. // TODO Auto-generated catch block
  57. e.printStackTrace();
  58. }
  59. }
  60. }
  61. }
  62. }
  63. }
  64.  
  65. //注解处理器
  66. private void injectAnotation() {
  67. //枚举实例化的bean
  68. for (String key : singletons.keySet()) {
  69. Object bean = singletons.get(key);
  70. if (bean != null) {
  71.  
  72. /*
  73. * 检查setter方法
  74. */
  75. try {
  76. PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
  77. //枚举每个bean的属性
  78. for (PropertyDescriptor p : ps) {
  79. Method setter = p.getWriteMethod();
  80. Object value = null;
  81. //存在set方法, 并且有setter上边有Resource注解
  82. if (setter != null && setter.isAnnotationPresent(GbxResource.class)){
  83. GbxResource gbxResource = setter.getAnnotation(GbxResource.class);
  84. //若有name 则按name查找
  85. if (gbxResource.name() != null && !"".equals(gbxResource.name())) {
  86. value = singletons.get(gbxResource.name());
  87. } else { //若没有,先安名字查找, 再按数据类型查找
  88. value = singletons.get(p.getName());
  89. if (value == null) {
  90. for (String key2 : this.singletons.keySet()) {
  91. if (p.getPropertyType().isAssignableFrom(this.singletons.get(key2).getClass())) {
  92. value = this.singletons.get(key2);
  93. break;
  94. }
  95. }
  96. }
  97. }
  98. setter.setAccessible(true);
  99. setter.invoke(bean, value);
  100. }
  101. }
  102. } catch (Exception e) {
  103. // TODO Auto-generated catch block
  104. e.printStackTrace();
  105. }
  106.  
  107. /*
  108. * 检查字段
  109. */
  110. Field[] fileds = bean.getClass().getDeclaredFields();
  111. for (Field field : fileds) {
  112. if (field.isAnnotationPresent(GbxResource.class)) {
  113. GbxResource gbxResource = field.getAnnotation(GbxResource.class);
  114. Object value = null;
  115. if (gbxResource.name() != null && !"".equals(gbxResource.name())) {
  116. value = this.singletons.get(gbxResource.name());
  117. } else {
  118. value = this.singletons.get(field.getName());
  119. if (value == null) {
  120. for (String key2 : this.singletons.keySet()) {
  121. if (field.getType().isAssignableFrom(this.singletons.get(key2).getClass())) {
  122. value = this.singletons.get(key2);
  123. break;
  124. }
  125. }
  126. }
  127. }
  128. field.setAccessible(true);
  129. try {
  130. field.set(bean, value);
  131. } catch (IllegalAccessException e) {
  132. e.printStackTrace();
  133. }
  134. }
  135. }
  136. }
  137. }
  138.  
  139. }
  140.  
  141. //实例化bean对象
  142. private void instanceBean() {
  143. for (DefBean bean : defBeans) {
  144. System.out.println(bean.getId() + " : " + bean.getClassName());
  145. if (bean.getClassName() != null && !"".equals(bean.getClassName())) {
  146. try {
  147. singletons.put(bean.getId(), Class.forName(bean.getClassName()).newInstance());
  148. } catch (Exception e) {
  149. e.printStackTrace();
  150. }
  151. }
  152. }
  153. }
  154. //读取xml文件
  155. private void readXML(String filename) {
  156. SAXReader reader = new SAXReader();
  157. Document document = null;
  158. URL xmlPath = this.getClass().getClassLoader().getResource(filename);
  159.  
  160. try {
  161. //的到document
  162. document = reader.read(xmlPath);
  163. //设置命名空间
  164. Map<String, String> nsMap = new HashMap<String, String>();
  165. nsMap.put("ns", "http://www.springframework.org/schema/beans");
  166. //创建查询路径
  167. XPath xPath = document.createXPath("//ns:beans/ns:bean");
  168. xPath.setNamespaceURIs(nsMap);
  169.  
  170. List<Element> beans = xPath.selectNodes(document);
  171. DefBean defBean = null;
  172. for (Element e : beans) {
  173. String id = e.attributeValue("id");
  174. String className = e.attributeValue("class");
  175. defBean = new DefBean(id, className);
  176.  
  177. XPath xPath2 = e.createXPath("ns:property");
  178. xPath2.setNamespaceURIs(nsMap);
  179. List<Element> propertys = xPath2.selectNodes(e);
  180.  
  181. DefProperty defProperty = null;
  182. for (Element e2 : propertys) {
  183. String name = e2.attributeValue("name");
  184. String ref = e2.attributeValue("ref");
  185. String value = e2.attributeValue("value");
  186.  
  187. defProperty = new DefProperty(name, ref, value);
  188. defBean.getDefPropertys().add(defProperty);
  189. }
  190. defBeans.add(defBean);
  191. }
  192. } catch (Exception e) {
  193. e.printStackTrace();
  194. }
  195. }
  196.  
  197. public Object getBean(String key) {
  198. return singletons.get(key);
  199. }
  200. }

  

  1. package cn.gbx.serviceimpl;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.HashMap;
  5. import java.util.HashSet;
  6. import java.util.List;
  7. import java.util.Map;
  8. import java.util.Properties;
  9. import java.util.Set;
  10.  
  11. import javax.annotation.Resource;
  12.  
  13. import org.springframework.beans.factory.annotation.Autowired;
  14.  
  15. import cn.gbx.daoimpl.PersonDao;
  16. import cn.gbx.example.GbxResource;
  17. import cn.gbx.service.PersonService;
  18.  
  19. public class PersonServiceImpl implements PersonService {
  20. @GbxResource
  21. private PersonDao personDao;
  22. private String name;
  23.  
  24. public void save() {
  25. personDao.save();
  26. System.out.println("Name = " + name);
  27. System.out.println("service层的 save方法");
  28. }
  29.  
  30. public void setPersonDao(PersonDao personDao) {
  31. this.personDao = personDao;
  32. }
  33.  
  34. public String getName() {
  35. return name;
  36. }
  37.  
  38. public void setName(String name) {
  39. this.name = name;
  40. }
  41.  
  42. public PersonDao getPersonDao() {
  43. return personDao;
  44. }
  45.  
  46. }

  

注解:

  1. package cn.gbx.example;
  2.  
  3. import java.lang.annotation.ElementType;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6. import java.lang.annotation.Target;
  7.  
  8. @Retention(RetentionPolicy.RUNTIME)
  9. @Target({ElementType.METHOD, ElementType.FIELD})
  10. public @interface GbxResource {
  11. public String name() default "";
  12. }

  

编码实现Spring 利用@Resource注解实现bean的注入,xml实现基本数据类型的注入的更多相关文章

  1. Spring学习--通过注解配置 Bean (三)

    组件装配: <context:component-sacan> 元素还会自动注册 AutowiredAnnotationBeanPostProcesser 实例 , 该实例可以自动装配具有 ...

  2. Spring 与 @Resource注解

    Spring 中支持@Autowired注解,能够实现bean的注入.同时,Spring 也支持@Resource注解,它和@Autowired类似,都是实现bean的注入.该注解存在javax.an ...

  3. Spring之使用注解实例化Bean并注入属性

    1.准备工作 (1)导入jar包 除了上篇文章使用到的基本jar包外,还得加入aop的jar包,所有jar包如下 所需jar包 (2)配置xml <?xml version="1.0& ...

  4. Spring学习--通过注解配置 Bean (二)

    在 classpath 中扫描组件: 当在组件类上使用了特定的注解之后 , 还需要在 Spring 的配置文件中声明 <context:component-scan>: base-pack ...

  5. Spring中@Resource注解报错

    描述:Spring框架中,@Resource注解报错,在书写时没有自动提示 解决方法:因为maven配置文件的pom.xml文件中缺少javax.annotation的依赖,在pom.项目路中加入依赖 ...

  6. Spring中用@DependsOn注解控制Bean的创建顺序

    1. 概述 Spirng容器自己会管理bean的生命周期和bean实例化的顺序,但是我们仍然可以根据我们自己的需求进行定制.我可以可以选择使用SmartLifeCycle接口,也可以用@Depends ...

  7. Spring_day01--Spring的bean管理(xml方式)_属性注入介绍

    Spring的bean管理(xml方式) Bean实例化的方式 1 在spring里面通过配置文件 创建对象 2 bean实例化(创建对象)三种方式实现 第一种 使用类的无参数构造创建(重点) Use ...

  8. spring利用扫描方式对bean的处理(对任何版本如何获取xml配置信息的处理)

    利用扫描的方式将组件注入容器,就也可以不用操作bean来实例化对象了. 下面我做一个例子 我用的spring3.2.2版本的 首先写一个spring.xml. <?xml version=&qu ...

  9. Spring学习--通过注解配置 Bean (一)

    在 classpath 中扫描组件: 组件扫描(component scanning): Spring 能够从 classpath 下自动扫描 , 侦测和实例化具有特定注解的组件. 特定组件包括: @ ...

随机推荐

  1. Android 常用工具类之RuntimeUtil

    public class RuntimeUtil { /** 通过查询su文件的方式判断手机是否root */ public static boolean hasRootedSilent() { re ...

  2. ORA-29339错误解决办法

    create tablespace TBS_JACK_16k blocksize 16k datafile '/u01/app/oracle/oradata/orcl/TBS_JACK_32K_01. ...

  3. [BIM]BIM中IDM介绍

    参考:http://blog.fang.com/25866228/10613454/articledetail.htm IDM的全称是Information Delivery Manual,信息交付手 ...

  4. ACM题目————二叉树的遍历

    一.二叉树的后序遍历: 题目描述 给定一颗二叉树,要求输出二叉树的深度以及后序遍历二叉树得到的序列.本题假设二叉树的结点数不超过1000 输入 输 入数据分为多组,第一行是测试数据的组数n,下面的n行 ...

  5. ACM题目————反约瑟夫问题

    题目描述 Description 著名的约瑟夫问题是这样描述的:N个人排成一个圆圈,然后把这N个人按逆时针方向编号为1.2.….N:随机产生 一个正整数M,然后从编号为1的人开始按逆时针计数,当某人计 ...

  6. android中文件操作的四种枚举

    1.MODE_PRIVATE:默认操作模式,代表该文件是私有数据,只能被应用自身访问,在该模式下,写入的的内容会覆盖原文件中的内容. 2.MODE_APPEND:该模式会检查文件是否存在,存在就往文件 ...

  7. Python 中translate()与replace()区别

    translate函数和replace函数一样,用于替换字符串中的某个部分,但是和replace不同,translate只处理单个字符,而且可以同时进行多个替换.在使用translate函数转换之前, ...

  8. [theWord] 一种英文字典的基类设计

    theWord --- 一种英文字典的基类设计 使用场景 想写一个应用,来记录自己背单词时候,对每个单词的记忆状况之类的东西.至于为什么做这个,试过了一些背单词软件,并不觉得好用,自己做一个吧. 那么 ...

  9. #ifdef DEBUG的理解

    今天看到一段代码,对ifdef的概念比较模糊,于是去学习了一下,找到一个很好的解释,如下: 在工程设置里有一些设置会对该工程自动产生一系列的宏,用以控制程序的编译和运行.就好象楼上说的一样,如果你把代 ...

  10. Mysql-学习笔记(==》数据库备份修复 十 四)

    CREATE DATABASE db USE db; CREATE TABLE stu( id INT UNSIGNED NOT NULL AUTO_INCREMENT, sname VARCHAR( ...