经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Spring » 查看文章
使用Spring自定义实现IOC和依赖注入(注解方式)
来源:jb51  时间:2021/8/16 16:34:53  对本文有异议

大致思路:

注解实现方式:

就是用 反射机制. 获取指定的包下使用了注解的类,存储在一个map容器, 然后获取map容器下类的属性, 利用反射给使用了注解的属性赋值对象.

xml实现方式:

使用xml解析配置文件+反射机制

此处使用注解方式

1. 引入相关jar

  1. <dependencies>
  2. <!-- 引入Spring-AOP等相关Jar -->
  3. <dependency>
  4. <groupId>org.springframework</groupId>
  5. <artifactId>spring-core</artifactId>
  6. <version>3.0.6.RELEASE</version>
  7. </dependency>
  8. <dependency>
  9. <groupId>org.springframework</groupId>
  10. <artifactId>spring-context</artifactId>
  11. <version>3.0.6.RELEASE</version>
  12. </dependency>
  13. <dependency>
  14. <groupId>org.springframework</groupId>
  15. <artifactId>spring-aop</artifactId>
  16. <version>3.0.6.RELEASE</version>
  17. </dependency>
  18. <dependency>
  19. <groupId>org.springframework</groupId>
  20. <artifactId>spring-orm</artifactId>
  21. <version>3.0.6.RELEASE</version>
  22. </dependency>
  23. <dependency>
  24. <groupId>org.aspectj</groupId>
  25. <artifactId>aspectjrt</artifactId>
  26. <version>1.6.1</version>
  27. </dependency>
  28. <dependency>
  29. <groupId>aspectj</groupId>
  30. <artifactId>aspectjweaver</artifactId>
  31. <version>1.5.3</version>
  32. </dependency>
  33. <dependency>
  34. <groupId>cglib</groupId>
  35. <artifactId>cglib</artifactId>
  36. <version>2.1_2</version>
  37. </dependency>
  38. <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
  39. <dependency>
  40. <groupId>com.mchange</groupId>
  41. <artifactId>c3p0</artifactId>
  42. <version>0.9.5.2</version>
  43. </dependency>
  44. <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
  45. <dependency>
  46. <groupId>mysql</groupId>
  47. <artifactId>mysql-connector-java</artifactId>
  48. <version>5.1.37</version>
  49. </dependency>
  50. <!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
  51. <dependency>
  52. <groupId>dom4j</groupId>
  53. <artifactId>dom4j</artifactId>
  54. <version>1.6.1</version>
  55. </dependency>
  56. <!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
  57. <dependency>
  58. <groupId>commons-lang</groupId>
  59. <artifactId>commons-lang</artifactId>
  60. <version>2.6</version>
  61. </dependency>
  62. </dependencies>

2. 定义注解类ExtService是注解类的, ExtResource是注解属性的

模拟@Service 和@Resource注解

在这里插入图片描述

在这里插入图片描述

3.定义一个借口

在这里插入图片描述

4. 接口和使用注解的实现类

在这里插入图片描述

在这里插入图片描述

5. 自定义实现ClassPathXmlApplicationContext

6.测试

在这里插入图片描述

7. 结果

在这里插入图片描述

8. 工具类

  1. package com.learn.utils;
  2. import java.io.File;
  3. import java.io.FileFilter;
  4. import java.io.IOException;
  5. import java.net.JarURLConnection;
  6. import java.net.URL;
  7. import java.net.URLDecoder;
  8. import java.util.ArrayList;
  9. import java.util.Enumeration;
  10. import java.util.LinkedHashSet;
  11. import java.util.List;
  12. import java.util.Set;
  13. import java.util.jar.JarEntry;
  14. import java.util.jar.JarFile;
  15. public class ClassUtil {
  16. /**
  17. * 取得某个接口下所有实现这个接口的类
  18. */
  19. public static List<Class> getAllClassByInterface(Class c) {
  20. List<Class> returnClassList = null;
  21. if (c.isInterface()) {
  22. // 获取当前的包名
  23. String packageName = c.getPackage().getName();
  24. // 获取当前包下以及子包下所以的类
  25. List<Class<?>> allClass = getClasses(packageName);
  26. if (allClass != null) {
  27. returnClassList = new ArrayList<Class>();
  28. for (Class classes : allClass) {
  29. // 判断是否是同一个接口
  30. if (c.isAssignableFrom(classes)) {
  31. // 本身不加入进去
  32. if (!c.equals(classes)) {
  33. returnClassList.add(classes);
  34. }
  35. }
  36. }
  37. }
  38. }
  39. return returnClassList;
  40. }
  41. /*
  42. * 取得某一类所在包的所有类名 不含迭代
  43. */
  44. public static String[] getPackageAllClassName(String classLocation, String packageName) {
  45. // 将packageName分解
  46. String[] packagePathSplit = packageName.split("[.]");
  47. String realClassLocation = classLocation;
  48. int packageLength = packagePathSplit.length;
  49. for (int i = 0; i < packageLength; i++) {
  50. realClassLocation = realClassLocation + File.separator + packagePathSplit[i];
  51. }
  52. File packeageDir = new File(realClassLocation);
  53. if (packeageDir.isDirectory()) {
  54. String[] allClassName = packeageDir.list();
  55. return allClassName;
  56. }
  57. return null;
  58. }
  59. /**
  60. * 从包package中获取所有的Class
  61. *
  62. * @param pack
  63. * @return
  64. */
  65. public static List<Class<?>> getClasses(String packageName) {
  66. // 第一个class类的集合
  67. List<Class<?>> classes = new ArrayList<Class<?>>();
  68. // 是否循环迭代
  69. boolean recursive = true;
  70. // 获取包的名字 并进行替换
  71. String packageDirName = packageName.replace('.', '/');
  72. // 定义一个枚举的集合 并进行循环来处理这个目录下的things
  73. Enumeration<URL> dirs;
  74. try {
  75. dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
  76. // 循环迭代下去
  77. while (dirs.hasMoreElements()) {
  78. // 获取下一个元素
  79. URL url = dirs.nextElement();
  80. // 得到协议的名称
  81. String protocol = url.getProtocol();
  82. // 如果是以文件的形式保存在服务器上
  83. if ("file".equals(protocol)) {
  84. // 获取包的物理路径
  85. String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
  86. // 以文件的方式扫描整个包下的文件 并添加到集合中
  87. findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes);
  88. } else if ("jar".equals(protocol)) {
  89. // 如果是jar包文件
  90. // 定义一个JarFile
  91. JarFile jar;
  92. try {
  93. // 获取jar
  94. jar = ((JarURLConnection) url.openConnection()).getJarFile();
  95. // 从此jar包 得到一个枚举类
  96. Enumeration<JarEntry> entries = jar.entries();
  97. // 同样的进行循环迭代
  98. while (entries.hasMoreElements()) {
  99. // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件
  100. JarEntry entry = entries.nextElement();
  101. String name = entry.getName();
  102. // 如果是以/开头的
  103. if (name.charAt(0) == '/') {
  104. // 获取后面的字符串
  105. name = name.substring(1);
  106. }
  107. // 如果前半部分和定义的包名相同
  108. if (name.startsWith(packageDirName)) {
  109. int idx = name.lastIndexOf('/');
  110. // 如果以"/"结尾 是一个包
  111. if (idx != -1) {
  112. // 获取包名 把"/"替换成"."
  113. packageName = name.substring(0, idx).replace('/', '.');
  114. }
  115. // 如果可以迭代下去 并且是一个包
  116. if ((idx != -1) || recursive) {
  117. // 如果是一个.class文件 而且不是目录
  118. if (name.endsWith(".class") && !entry.isDirectory()) {
  119. // 去掉后面的".class" 获取真正的类名
  120. String className = name.substring(packageName.length() + 1, name.length() - 6);
  121. try {
  122. // 添加到classes
  123. classes.add(Class.forName(packageName + '.' + className));
  124. } catch (ClassNotFoundException e) {
  125. e.printStackTrace();
  126. }
  127. }
  128. }
  129. }
  130. }
  131. } catch (IOException e) {
  132. e.printStackTrace();
  133. }
  134. }
  135. }
  136. } catch (IOException e) {
  137. e.printStackTrace();
  138. }
  139. return classes;
  140. }
  141. /**
  142. * 以文件的形式来获取包下的所有Class
  143. *
  144. * @param packageName
  145. * @param packagePath
  146. * @param recursive
  147. * @param classes
  148. */
  149. public static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive,
  150. List<Class<?>> classes) {
  151. // 获取此包的目录 建立一个File
  152. File dir = new File(packagePath);
  153. // 如果不存在或者 也不是目录就直接返回
  154. if (!dir.exists() || !dir.isDirectory()) {
  155. return;
  156. }
  157. // 如果存在 就获取包下的所有文件 包括目录
  158. File[] dirfiles = dir.listFiles(new FileFilter() {
  159. // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)
  160. public boolean accept(File file) {
  161. return (recursive && file.isDirectory()) || (file.getName().endsWith(".class"));
  162. }
  163. });
  164. // 循环所有文件
  165. for (File file : dirfiles) {
  166. // 如果是目录 则继续扫描
  167. if (file.isDirectory()) {
  168. findAndAddClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive,
  169. classes);
  170. } else {
  171. // 如果是java类文件 去掉后面的.class 只留下类名
  172. String className = file.getName().substring(0, file.getName().length() - 6);
  173. try {
  174. // 添加到集合中去
  175. classes.add(Class.forName(packageName + '.' + className));
  176. } catch (ClassNotFoundException e) {
  177. e.printStackTrace();
  178. }
  179. }
  180. }
  181. }
  182. }

以上为个人经验,希望能给大家一个参考,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号