小白一个 分享一下如何实现ioc di功能
先上项目图 这个包是专门用来练习的 所以懒得换地方了 就写在pack6包下 整体看起来不是很好
![整个项目就pack6这个包](https://i-blog.csdnimg.cn/blog_migrate/39ad1dda35c548e588ebd510634f5d0e.png)
controller包
package test.pack6.controller;
import test.pack6.ioc.MyAuto;
import test.pack6.ioc.Scan;
import test.pack6.service.DemoService;
@Scan(value = "demoController")
public class DemoController {
@MyAuto
public DemoService demoService;
public DemoController() {
//demoService.show();
System.out.println("controller触发");
}
}
service包
package test.pack6.service;
import test.pack6.dao.DemoDao;
import test.pack6.ioc.MyAuto;
import test.pack6.ioc.Scan;
@Scan(value = "demoService")
public class DemoService {
@MyAuto
public DemoDao demoDao;
public DemoService() {
System.out.println("service触发");
}
public void show() {
System.out.println("service的show方法");
}
}
dao包
package test.pack6.dao;
import test.pack6.ioc.Scan;
@Scan(value="demoDao")
public class DemoDao {
public DemoDao() {
System.out.println("demoDao触发");
}
public void show() {
System.out.println("daoshow的show方法");
}
}
@Scan和@MyAuto都是自定义注解
@MyAuto打在属性上的 @Scan打在类上 并且value上的值是ioc生成的对象名也就是下面的id map的key
package test.pack6.ioc;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(value = { ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Scan {
String value();
}
package test.pack6.ioc;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(value = ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAuto {
}
模拟spring环境下的主函数
package test.pack6;
import test.pack6.controller.DemoController;
import test.pack6.ioc.MyMainClass;
import test.pack6.service.DemoService;
public class MainClass {
public static void main(String[] args) {
new MyMainClass(new MainClass());
DemoService demoService = (DemoService) MyMainClass.map.get("demoService");
demoService.demoDao.show();
DemoController demoController = (DemoController) MyMainClass.map.get("demoController");
demoController.demoService.show();
}
}
本来是想在构造方法里调用demoService.show()方法的 因为我是先实现ioc功能 再去实现di功能的
写在构造函数里 会报空指针异常 因为这个时候demoService的属性还未注入
所以写在了主函数里 当然主函数里是没问题的
package test.pack6.ioc;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.concurrent.ConcurrentHashMap;
public class MyMainClass {
public static ConcurrentHashMap<String, Object> map;
public static Object object;
public static File[] controllerFiles;
public static File[] serviceFiles;
public static File[] daoFiles;
public static StringBuilder controllerPath;
public static StringBuilder servicePath;
public static StringBuilder daoPath;
//传入主函数的对象 调用getClazz()
//dao service 和controller方法都是一样的 所以controller方法看懂了
//其他的都一样了
public MyMainClass(Object object) {
MyMainClass.object = object;
getClazz();
map = new ConcurrentHashMap<>();
dao();
service();
controller();
}
public void controller() {
// 先遍历controller包下的所有.java文件
for (File file : controllerFiles) {
// 分割.java文件 获取类名
StringBuilder str = new StringBuilder(file.getName().split("\\.")[0]);
// 把项目里的\转为. 否则找不到该类
//项目路径是以\隔开的 所以要替换为. 这里用了replace方法
String s1 = controllerPath.toString().replace("\\", ".");
// 包名+类名
String s = s1 + "." + str;
try {
//判断类上是否有该注解 并把注解值设置为id 也就是map的key
if (Class.forName(s).isAnnotationPresent(Scan.class)) {
String id = Class.forName(s).getAnnotation(Scan.class).value();
//创建实例
Object obj = Class.forName(s).newInstance();
map.put(id, obj);
//获取类上的属性
Field[] fields = Class.forName(s).getDeclaredFields();
for (Field field : fields) {
//判断属性上是否有该注解
if (field.isAnnotationPresent(MyAuto.class)) {
// 根据field.getName()就是上面的key 所以这里比较严谨 要求一一对应
Object object = map.get(field.getName());
//将把object属性放入原对象obj里 也就是放进原对象的属性里
field.set(obj, object);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void service() {
for (File file : serviceFiles) {
StringBuilder str = new StringBuilder(file.getName().split("\\.")[0]);
String s1 = servicePath.toString().replace("\\", ".");
String s = s1 + "." + str;
try {
if (Class.forName(s).isAnnotationPresent(Scan.class)) {
String id = Class.forName(s).getAnnotation(Scan.class).value();
Object obj = Class.forName(s).newInstance();
map.put(id, obj);
Field[] fields = Class.forName(s).getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(MyAuto.class)) {
// 根据key取对象
Object object = map.get(field.getName());
field.set(obj, object);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void dao() {
for (File file : daoFiles) {
StringBuilder str = new StringBuilder(file.getName().split("\\.")[0]);
String s1 = daoPath.toString().replace("\\", ".");
String s = s1 + "." + str;
try {
if (Class.forName(s).isAnnotationPresent(Scan.class)) {
String id = Class.forName(s).getAnnotation(Scan.class).value();
Object obj = Class.forName(s).newInstance();
map.put(id, obj);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void getClazz() {
try {
// 获取当前项目下的main函数的包名
String str = object.getClass().getPackage().getName().replace(".", "\\");
StringBuilder pack = new StringBuilder(str);
// 得到的是项目名的路径 所以要加上src文件名 否则找不到这个文件
// pack=test\pack6
StringBuilder path = new StringBuilder("\\src\\" + pack);
// 获取项目的绝对路径 这个路径是项目的完整路径
//filePath = C:\Users\samsung\eclipse-workspace\note\src\test\pack6
String filePath = new File("").getCanonicalPath() + path;
//根据路径生成file对象
File file = new File(filePath);
File[] files = file.listFiles();
//controllerPath是这个项目下controller包的路径
//controllerFiles是controller下的所有文件名 也就是.java文件
//service 和 dao 同理
for (File file2 : files) {
String st = file2.getName();
// 包含controller字眼的包
if (st.contains("controller")) {
// 获取项目下controller包完整路径test\pack6\controller
controllerPath = new StringBuilder(pack + "\\" + file2.getName());
if (file2.isDirectory()) {
// 获取该包下的所有文件
controllerFiles = file2.listFiles();
}
} else if (st.contains("service")) {
servicePath = new StringBuilder(pack + "\\" + file2.getName());
if (file2.isDirectory()) {
serviceFiles = file2.listFiles();
}
} else if (st.contains("dao")) {
daoPath = new StringBuilder(pack + "\\" + file2.getName());
if (file2.isDirectory()) {
daoFiles = file2.listFiles();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}