如何实现ioc di(控制反转)

小白一个 分享一下如何实现ioc di功能

先上项目图 这个包是专门用来练习的 所以懒得换地方了 就写在pack6包下 整体看起来不是很好
整个项目就pack6这个包
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();
		}
	}

}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值