IOC: 控制反转. 它是怎么实现的呢?
首先, 要先定义需要控制反转的范围, 也就是确定哪些.class文件需要. 那我们首先找到项目下的所有 .class 文件.
建立一个普通java工程

在 ClassUtil中定义一个方法来获取当前线程

定义一个方法获取指定包名下的所有类

在getClassSet方法内使用
Enumeration<URL> urls = getClassLoader().getResources(pkgName.replace(".", "/"));
进行枚举.
开始遍历

最后整理一下
public static Set<Class<?>> getClassSet(String pkgName) {
Set<Class<?>> classSet = new HashSet<>();
try {
Enumeration<URL> urls = getClassLoader().getResources(pkgName.replace(".", "/"));
while(urls.hasMoreElements()) { // 遍历
URL url = urls.nextElement();
if(url != null) {
String protocol = url.getProtocol(); // 获取协议, 防止可能有压缩包那些
if("file".equals(protocol)) { // 类型是文件
String pkgPath = url.getPath().replace("%20", " ");// 空格问题
addClass(classSet, pkgPath, pkgName); // 调用addClass方法
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return classSet;
}
在遍历循环内我们调用了 addClass方法, 这个方法用来添加类
private static void addClass (Set<Class<?>> classSet, String pkgPath, String pkgName) {
// 放入 files 的条件
File[] files = new File(pkgPath).listFiles(file -> (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory());
for(File file : files != null ? files : new File[0]) {
String fileName = file.getName();
if(file.isFile()) { // 是文件而不是包, 同时也是递归的出口
String className = fileName.substring(0, fileName.lastIndexOf(".")); // 字符串截断, 去掉后面的 .class
if(!pkgName.isEmpty()) {
className = pkgName + "." + className;
}
addClass(classSet, className);
}else { // 不是文件的情况, 需要进入这个目录向下
String subPath = "/" + fileName;
if(!pkgPath.isEmpty()) {
subPath = pkgPath + subPath;
}
String subName = "." + fileName;
if(!pkgPath.isEmpty()) {
subName = pkgName + subName;
}
// 递归调用
addClass(classSet, subPath, subName);
}
}
}
private static void addClass (Set<Class<?>> classSet, String className) { System.out.println(className); // 直接打印看看结果 }
接下来我们写一个测试类
@Test
public void test1() {
ClassUtil.getClassSet("tech");
}
运行结果:
可以看到我们写的所有.class文件名都被打印了出来.
控制反转是基于java的反射来实现的, 我们将所有的.class类都新建出来, 并放入一个容器中.
修改 addClass方法
private static void addClass (Set<Class<?>> classSet, String className) { Class<?> aClass = loadClass(className, false); classSet.add(aClass); }
在addClass方法中调用loadClass, 用来反射生成,并将结果装入classSet.
public static Class<?> loadClass(String className, boolean isInitialized){ Class<?> cls; try { cls = Class.forName(className,isInitialized,getClassLoader()); } catch (ClassNotFoundException e) { e.printStackTrace(); throw new RuntimeException(e); } return cls; }
我们测试一下.
@Test public void test1() { for(Class<?> aClass : ClassUtil.getClassSet("tech")) { System.out.println(aClass); } }
结果

我们知道, Spring是通过注解来进行识别的, 通过注解进行自动装配, 自动生成, 并且解决类的内部域, 方便开发, 接下来我们使用自定义注解实现基本的功能
2282

被折叠的 条评论
为什么被折叠?



