自定义基于spring注解配置的原理及代码实现

1.spring理解

spring说白了就是一个容器,相当于一个工厂,让一个对象的创建不用new,可以自动生产。它的核心是IOC(反转控制)和DI(依赖注入)这其实就是利用了java中的反射机制。反射其实就是在运行时动态去创建,调用对象。Spring就是在运行时,跟xml Spring的配置文件来动态的创建对象,和调用对象里的方法的 理解了spring的底层原理之后,里面的属性各方面的值就可以直接用Map去存  

2.代码实现

2.1 先写一个自定义接口,里面写一个getBean(int id)

2.2在写一个类去实现自定义接口并在这个类里面的构造方法写入解析代码(采用jdom解析原理),代码如下

2.3自己写一个application.xml去测试

public SelfClassPathXmlApplicationContext(String xmlPath){       
          //1. 读取  xmlpath 文件
		SAXBuilder sb = new SAXBuilder();	//jdom才底层采用sax解析方式
		// 2.  解析 xml  -> dom -> 一次性加载整棵树,以dom模型解析,  sax -》 流的方式加载数据,以事件的方式来解析xml
		InputStream iis = this.getClass().getClassLoader().getResourceAsStream(xmlPath);
		Document doc = sb.build(iis);
		Element rootElement = doc.getRootElement();
		//3.得到所有的bean,是list列表
		List<Element> list = rootElement.getChildren();
		//4.循环这个list列表
		for (Element ele : list) {
			//5.取出id,class
			String id = ele.getAttributeValue("id");
			String classPath = ele.getAttributeValue("class");
			//6.以反射方式根据class值来创建一个object对象(调用了这个对象的无参构造方法)
			Object obj = Class.forName(classPath).newInstance();	//无参构造方法
			//7. beans.put(id.obj)
			beans.put(id, obj);取  xmlpath 文件

             //8.查看这个bean下是否有子节点 property
			//9.如果有,则循环所有的子节点,取出name value ref
			for (Element proElement :(List<Element>)ele.getChildren()) {
				String name = proElement.getAttributeValue("name");
				String value = proElement.getAttributeValue("value");
				String ref = proElement.getAttributeValue("ref");
				
				//取出对应的setXxx()方法  set + name 首字母大写
				String methodName = "set"+name.substring(0, 1).toUpperCase()+name.substring(1);
				//从Class中找到这个方法
				Method m = findMethod(methodName,classPath);
				if(m==null) {
					continue;
				}
				//m就是一个setXxx()方法,他只有一个参数,但getParameters()会取出多个参数
				String typename = m.getParameters()[0].getType().getName();
				// setSid 的参数类型为:java.lang.reflect.Parameter
				System.out.println(m.getName()+"的参数类型为:" +typename);
				//10.判断是value吗?
				if(value!=null) {
					//是,则在class对象找set Name这个方法
					//如有这个setXxx()方法  则激活
					if("int".equals(typename) || "java.lang.Integer".equals(typename)) {
						//parseInt() 函数可解析一个字符串,并返回一个整数
						int v = Integer.parseInt(value);
						m.invoke(obj, v);
					}else if("float".equals(typename) ||     "java.lang.Float".equals(typename)) {
						float v = Float.parseFloat(value);
						m.invoke(obj, v);
					}else if("double".equals(typename) || "java.lang.Double".equals(typename)) {
						double v = Double.parseDouble(value);
						m.invoke(obj, v);
					}else {
						m.invoke(obj, value);
					}
					
				}else if(ref!=null) {    //11.判断ref不为空
					//TODO: 
					Object toInjectObject = beans.get(ref);
					System.out.println("toInjectObject==>" +toInjectObject);
					m.invoke(obj, toInjectObject);
				}
				
		}
}

//写一个方法去循环放射对象中的所有方法
private Method findMethod(String methodName,String classPath) throws ClassNotFoundException {
		Class c = Class.forName(classPath);
		Method[] ms = c.getMethods();
		for (Method m : ms) {
			if(m.getName().equals(methodName)) {
				return m;
			}
		}
		return null;
	}
		

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值