手工实现spring的ioc

        一小段时间没有使用spring,对spring一些基础要点都开始遗忘了,所以趁着现在比较有时间,来模拟一个spring的一小块功能:ioc,毕竟,好记性不如烂笔头,这样能够加深自己对spring的理解。

在此先附上一份demo,作为环境。

项目结构



package entity;

public class Product {
	private int pId;
	private String pName;
	private String Paddress;

	public int getpId() {
		return pId;
	}

	public void setpId(int pId) {
		this.pId = pId;
	}

	public String getpName() {
		return pName;
	}

	public void setpName(String pName) {
		this.pName = pName;
	}

	public String getPaddress() {
		return Paddress;
	}

	public void setPaddress(String paddress) {
		Paddress = paddress;
	}

}



package Dao;

import entity.Product;

public class ProductDaoImpl implements ProductDao {

	@Override
	public void add(Product p) {
		System.out.println("sava success");
		System.out.println(p.getpName());
	}

}

package Service;

import Dao.ProductDao;
import Dao.ProductDaoImpl;
import entity.Product;

public class ProductServiceImpl implements ProductService {
	ProductDao pd=new ProductDaoImpl();
	@Override
	public void add(Product p) {
		pd.add(p);
	}

	
}
package test;

import org.junit.Before;
import org.junit.Test;

import Service.ProductService;
import Service.ProductServiceImpl;
import entity.Product;

public class ProductTest {
	Product product = null;

	@Before
	public void bef() {
		product = new Product();
		product.setpId(1);
		product.setPaddress("school");
		product.setpName("phone");
	}

	@Test
	public void testProduct() {
		ProductService ps = new ProductServiceImpl();
		ps.add(product);
	}
}

运行junit单元测试,控制台打印如下所示:

sava success
phone

以上是,我们是手动new对象,手动管理这些对象。

现在,我们来设计一个能够实现类似spring的iop的类,让它为我们创建对象,当程序中需要使用到这个对象,则自动住入到需要该对象的地方。

设计思路:让它创建什么类的对象? 它如何将对象注入到我们引用该对象的地方?

主要技术支持:java的反射机制,xml 的dom操作。

在这里我使用的是dom4j-1.6.1.jar这个包的SAXReader类。就是用来创建解析器对象的,解析的方法很多,目前,我就用过了这种,所以呢,在这我就使用的是这种方法。

bean.xml

<beans>
	<bean id="productDao" class="Dao.ProductDaoImpl" />
	<bean id="productService" class="Service.ProductServiceImpl">
		<property name="productDao" bean="productDao" />
	</bean>
</beans>  


ClassPathXmlApplicationContext.java

package Factory;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class ClassPathXmlApplicationContext implements Beanfactory {

	private Map<String, Object> beans = new HashMap<String, Object>();

	// 构造函数
	public ClassPathXmlApplicationContext() {
		try {
			// 1创建解析器对象
			SAXReader saxReader = new SAXReader();
			// 使用解析器加载bean.xml文件得到document对象
			Document document = saxReader.read("src/bean.xml");
			// 获得根元素的节点
			Element root = document.getRootElement();
			// 根据元素获取所有bean元素
			List beanElements = root.elements("bean");
			//遍历所有的bean元素
			for (int i = 0; i < beanElements.size(); i++) {
				//获取第i个bean
				Element beanElement = (Element) beanElements.get(i);
				//获取bean对象的id属性的值
				String id = beanElement.attributeValue("id");
				//获取class属性的值
				String classPath = beanElement.attributeValue("class");
				//输出便于分析调试
				System.out.println(id);
				System.out.println(classPath);
				//使用反射创建(classPath这个字符串对应值的类)的对象
				Object o = Class.forName(classPath).newInstance();
				//将这个对象添加到这个map中
				beans.put(id, o);
				//获得这个bean依赖的对象,接下来的方法一样,不注释了
				List propertyElements = beanElement.elements("property");
				for (Element propertyElement : (List<Element>) propertyElements) {
					String name = propertyElement.attributeValue("name");
					String bean = propertyElement.attributeValue("bean");
					System.out.println(name);
					System.out.println(bean);
					Object beanObject = beans.get(bean);
					//下面就是构造出ProductServiceImpl类中方法的方法名,此例子为setProductDao
					String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
					System.out.println("method name = " + methodName);
					//获得ProductServiceImpl类中的setProductDao()方法的方法对象
					Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]);
					//使用反射执行该方法,也就是注入依赖的对象,此例子为productDao
					m.invoke(o, beanObject);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/**
	 * 对外开放一个方法,使得外界能够根据需要直接拿到这个beans这个map中bean。
	 */
	@Override
	public Object getBean(String id) {
		return beans.get(id);
	}

}

ProductServiceImpl.java

package Service;

import Dao.ProductDao;
import entity.Product;

public class ProductServiceImpl implements ProductService {
	private ProductDao productDao;
	
	@Override
	public void add(Product p) {
		productDao.add(p);
	}

	public void setProductDao(ProductDao pd) {
		this.productDao = pd;
	}
	
}

ProductDaoImpl.java


package Dao;

import entity.Product;

public class ProductDaoImpl implements ProductDao {

	@Override
	public void add(Product p) {
		System.out.println("sava success");
		System.out.println(p.getpName());
	}

}

testSpring.java

package test;

import org.junit.Test;

import Factory.ClassPathXmlApplicationContext;
import Service.ProductService;
import entity.Product;

public class testSpring {
	@Test
	public void Test(){
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
		ProductService ps =(ProductService) context.getBean("productService");
		Product product = new Product();
		product.setpId(1);
		product.setPaddress("school");
		product.setpName("phone");
		ps.add(product);
	}
	
}




控制台输出:

productDao
Dao.ProductDaoImpl
productService
Service.ProductServiceImpl
productDao
productDao
method name = setProductDao
sava success
phone

输出结果与预计一致,在这只是模拟spring的ioc,依赖注入,所以灵活性还是不好,但是基本理念是体现出来了。

麻雀虽小,五腑俱全

接下来有相关的东西继续更新中,喜欢的朋友可以关注下。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值