重复造轮子--SpringIOC容器

主要步骤:加载配置文件,实例化bean,填充bean属性,返回bean。

项目目录结构:
在这里插入图片描述
1.创建一个对象Student

public class Student {
	
	private Integer id;
	private String name;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + "]";
	}

}

2.创建StudentDao

public class StudentDao {
	
	private String test;
	
	public String getTest() {
		return test;
	}
	public void setTest(String test) {
		this.test = test;
	}

	public void sayHello() {
		System.out.println("hello world");
	}

}

3.创建StudentService

public class StudentService {
	//注入dao
	private StudentDao studentDao;

	public void setStudentDao(StudentDao studentDao) {
		this.studentDao = studentDao;
	}
	public StudentDao getStudentDao() {
		return studentDao;
	}
	public void sayHello() {
		studentDao.sayHello();
	}
}

4.bean配置文件applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans>
   
     <bean id="student" class="stu.wf.beans.Student" scope="single">
        <property name="id" value="1"></property>
        <property name="name" value="张三"></property>
     </bean>
     
     <bean id="studentDao" class="stu.wf.dao.StudentDao" scope="single">
     	<property name="test" value="test"></property>
     </bean>
     
     <bean id="studentService" class="stu.wf.service.StudentService" scope="single">
        <property name="studentDao" ref="studentDao"></property>
     </bean>

</beans>

5.最重要的逻辑处理ApplicationContext

public class ApplicationContext {
	
	/**
	 * 保存单例bean
	 */
	private static Map<String, Object> singleBeans = new HashMap<>();
	
	private static Document document = null;
	private static ApplicationContext context = null;
	
	public static ApplicationContext buildContext(String configPath) {
		if(context == null) {
			SAXReader reader = new SAXReader();
			try {
				document = reader.read(configPath);
				instanceSingleBean();
				context = new ApplicationContext();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return context;
	}
	
	/**
	 * 实例化所有单例bean 保存到singleBeans中
	 * @param document
	 * @throws Exception
	 */
	private static void instanceSingleBean()throws Exception{
		String xpath = "//bean[@scope='single']";
		@SuppressWarnings("unchecked")
		List <Element> elements = document.selectNodes(xpath);
		for(Element element : elements) {
			String classPath = element.attributeValue("class");
			Object obj = Class.forName(classPath).newInstance();
			singleBeans.put(classPath, obj);
		}
	}
	
	public Object getBean(String beanId) {
		Object resultObj = null;
		String xpath = "//bean[@id='"+beanId+"']";
		@SuppressWarnings("unchecked")
		List<Element> elements = document.selectNodes(xpath);
		if(elements == null || elements.size()<1) {
			throw new RuntimeException("beanId:"+beanId+" is error");
		}else if(elements.size()>1) {
			throw new RuntimeException("beanId:"+beanId+" not only one bean.");
		}
		Element element = elements.get(0);
		String classPath = element.attributeValue("class");
		resultObj = singleBeans.get(classPath);
		
			try {
				if(resultObj == null) {
					resultObj = Class.forName(classPath).newInstance();
				}
				
				//填充bean属性 -- 简单依赖注入
				initBean(resultObj,element);
			} catch (Exception e) {
				e.printStackTrace();
			}
		return resultObj;
	}

	/**
	 * 填充bean屬性
	 * @param resultObj
	 * @param beanElement
	 * @throws Exception
	 * @throws SecurityException
	 */
	private void initBean(Object resultObj, Element beanElement) throws Exception, SecurityException {
		@SuppressWarnings("unchecked")
		List<Element> properTyElements = beanElement.elements("property");
		if(properTyElements == null || properTyElements.size()<1) {
			return ;
		}
		
		for(Element property : properTyElements) {
			String fieldName = property.attributeValue("name");
			String fieldValue = property.attributeValue("value");
			String fieldRef = property.attributeValue("ref");
			//对应的属性
			Field field = resultObj.getClass().getDeclaredField(fieldName);
			String typeName = field.getType().getName();
			if(fieldRef != null && !"".equals(fieldRef)) {
				setPropertyRef(resultObj,field,fieldRef);
			}else {
				setProperTyValue(resultObj,field,typeName,fieldValue);
			}
		}
	}

	/**
	 * 简单判断,Integer String类型的属性
	 * @param resultObj
	 * @param field
	 * @param typeName
	 * @param fieldValue
	 * @throws Exception
	 */
	private void setProperTyValue(Object resultObj, Field field, String typeName, String fieldValue)throws Exception {
		field.setAccessible(true);
		 if("java.lang.String".equals(typeName)){
		    	field.set(resultObj, fieldValue);
		    }else if("java.lang.Integer".equals(typeName)){
		    	field.set(resultObj, Integer.valueOf(fieldValue));
		    }
	}

	/**
	 * 处理属性也是个bean  依赖注入
	 * @param resultObj
	 * @param field
	 * @param fieldRef
	 * @throws Exception
	 */
	private void setPropertyRef(Object resultObj, Field field, String fieldRef) throws Exception{
		String xPath="//bean[@id='"+fieldRef+"']";
		Element beanElement = (Element) document.selectNodes(xPath).get(0);
		String classPath = beanElement.attributeValue("class");
		Object refObj = singleBeans.get(classPath);
		if(refObj == null) {
			refObj = Class.forName(classPath).newInstance();
		}
		//TODO  这里的引用refObj只是实例化了,本没有填充属性
		field.setAccessible(true);
		field.set(resultObj, refObj);
	}

}

6.测试类TestMain

public class TestMain {
	public static void main(String[] args) {
		ApplicationContext context = ApplicationContext.buildContext("src/applicationContext.xml");
		Student student = (Student)context.getBean("student");
		System.out.println("student:"+student);
		StudentService studentService = (StudentService)context.getBean("studentService");
		studentService.sayHello();
		System.out.println("test:"+studentService.getStudentDao().getTest());
	}

}

运行结果:

student:Student [id=1, name=张三]
hello world
test:null  //并没有循环依赖注入,所有dao的属性为null
发布了42 篇原创文章 · 获赞 29 · 访问量 2541

猜你喜欢

转载自blog.csdn.net/qq_32314335/article/details/103547977