模拟IOC简易扫描器

Posted africanhusky

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模拟IOC简易扫描器相关的知识,希望对你有一定的参考价值。

浅析xml文件中的IOC自动扫描器原理

 <context:component-scan base-package="cn.scanner"/>

第一步:获取自动扫描的package的范围

base-package="cn.scanner"

第二步:获取指定范围内的包中的所有class文件

D:/java_project/week14_03_spring01/target/classes/cn/scanner
D:/java_project/week14_03_spring01/target/classes/cn/scanner/controller
.....

第三步:判断class文件中是否标注了指定的注解

如果标注了注解,则实例化类对象

 

附本地的文件夹结构

技术分享图片

技术分享图片
 1 public class AutoScanner {
 2     private static List<String> clazz = new ArrayList<>();
 3     private static Map<String,Object> map = new HashMap<>();
 4     public static void main(String[] args){
 5         //设置扫描的范围为cn.scanner包下的所有内容
 6         String sourcePackage = "cn.scanner";
 7         //调用方法 获取该范围下所有类的全限定名
 8         getAllClass(sourcePackage);
 9         //实例化对象
10         instanceBeans();
11     }
12 
13     /**
14      * 实例化已存在,并且标识了注释的类
15      */
16     public static void instanceBeans(){
17         //判断集合是否无内容
18         if(clazz.size()>0){
19             //遍历全限定名集合
20             for(String str : clazz){
21                 try {
22                     //尝试从被扫描到的类中获取注解对象
23                     TestAnnotation testAnnotation = Class.forName(str).getAnnotation(TestAnnotation.class);
24                     //如果当前类未标识该注释 则注释对象为空
25                     if(null != testAnnotation){
26                         //通过全限定名实例化类对象
27                         Object obj = Class.forName(str).newInstance();
28                         //截取全限定名 只保留最后一个‘.‘后的内容
29                         str = str.substring(str.lastIndexOf(".")+1);
30                         //遵循spring框架的id命名规则 首字母小写 后面的字符保持不变
31                         String key = str.toLowerCase().charAt(0)+str.substring(1);
32                         map.put(key,obj);
33                     }
34                 } catch (Exception e) {
35                     e.printStackTrace();
36                 }
37             }
38         }
39     }
40 
41     /**
42      * 获取类的全限定名集合
43      * @param sourcePackage
44      */
45     private static void getAllClass(String sourcePackage) {
46         System.out.println("当前在:"+sourcePackage+"包中");
47         //由于在方法中无法调用this,所以只能调用当前线程的类加载器来获取url
48         URL url = Thread.currentThread().getContextClassLoader().getResource(replacePath(sourcePackage));
49         String basePath = url.getPath();
50         System.out.println("当前包的完整路径:"+basePath);
51         //用于储存当前路径下的所有文件的路径
52         String[] subPaths = new File(basePath).list();
53         for(String sub : subPaths){
54             String subFilePath = basePath+"/"+sub;
55             File subFile = new File(subFilePath);
56             System.out.println("扫描到文件:"+subFile.getName());
57             //判断该文件是否为文件夹
58             if(subFile.isDirectory()){
59                 System.out.println("	该文件是文件夹");
60                 System.out.println("	进入"+subFile.getName()+"包中");
61                 getAllClass(sourcePackage+"."+subFile.getName());
62             }else{
63                 System.out.println("	该文件不是文件夹");
64                 String fullName = sourcePackage+"."+subFile.getName();
65                 fullName = fullName.replace(".class","");
66                 //如果该文件不是文件夹,则将它的全限定名存入集合备用
67                 clazz.add(fullName);
68                 System.out.println("	将文件的全限定名"+fullName+"存入集合中");
69             }
70         }
71     }
72 
73     /**
74      * 将字符串中的‘.‘转换为‘/‘
75      * @param str
76      * @return
77      */
78     private static String replacePath(String str){
79         return str.replaceAll("\\.","\\/");
80     }
81 }
简易IOC扫描器
技术分享图片
当前在:cn.scanner包中
当前包的完整路径:/D:/java_project/week14_03_spring01/target/classes/cn/scanner
扫描到文件:AutoScanner.class
    该文件不是文件夹
    将文件的全限定名cn.scanner.AutoScanner存入集合中
扫描到文件:controller
    该文件是文件夹
    进入controller包中
当前在:cn.scanner.controller包中
当前包的完整路径:/D:/java_project/week14_03_spring01/target/classes/cn/scanner/controller
扫描到文件:TestController.class
    该文件不是文件夹
    将文件的全限定名cn.scanner.controller.TestController存入集合中
扫描到文件:dao
    该文件是文件夹
    进入dao包中
当前在:cn.scanner.dao包中
当前包的完整路径:/D:/java_project/week14_03_spring01/target/classes/cn/scanner/dao
扫描到文件:TestDao.class
    该文件不是文件夹
    将文件的全限定名cn.scanner.dao.TestDao存入集合中
扫描到文件:service
    该文件是文件夹
    进入service包中
当前在:cn.scanner.service包中
当前包的完整路径:/D:/java_project/week14_03_spring01/target/classes/cn/scanner/service
扫描到文件:TestService.class
    该文件不是文件夹
    将文件的全限定名cn.scanner.service.TestService存入集合中
扫描到文件:TestAnnotation.class
    该文件不是文件夹
    将文件的全限定名cn.scanner.TestAnnotation存入集合中
对应输出的内容

如有写错的地方,希望有研究的朋友指出,谢谢!



以上是关于模拟IOC简易扫描器的主要内容,如果未能解决你的问题,请参考以下文章

Shell外壳的简易模拟

Java模拟Sping,实现其IOC和AOP核心

手写一个简易的IOC

手写实现自定义简易版Spring (实现IoC 和 AOP)

手写实现自定义简易版Spring (实现IoC 和 AOP)

利用反射做一个简易 Spring IOC 容器,模仿其装配功能