关于ClassPathXMLApplicationContext 重写的一些原理和代码

这些天刚学习了一点spring框架的一点东西,看了很多大神的理解和看法,关于spring框架 其中有几大模块但是总的来说分为两种思想,意识oop思想也就是java语言的核心思想面向对象编程,但是spring还有一种就是aop也就是面向方面编程,这也是spring框架比较的优点吧。
这里我们不讨论这个,先来说说入门的ioc 以及ClassPathXMLApplicationContext 的简单重写吧
IOC(inversion of control)控制反转

     概念:控制权由对象本身转向容器;由容器根据配置文件去创建实例并创建各个实例之间的依赖关系。

     核心:spring封装了抽象工厂模式;bean工厂创建的各个实例称作为bean。

     理解:喜欢吃的东西不一定自己亲自去做,交给食品加工厂去做不是更好吗。spring让一个对象不用创建new了,可以自动生产,这就是利用Java的反射机制动态创建、调用对象,spring就是在运行时,根xml 是pring配置文件动态创建对象,和调用对象里的方法的。

     spring IOC 应用了单例模式,一次new一个全局对象,也可以在配置文件中进行配置,配置为不使用单例模式。

切面编程:Spring提供了切面编程的丰富支持,允许分离应用的业务逻辑与服务。

容器:Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建—一个可配置的原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例,以及它们是如何关联的。

框架:Spring可以将简单的组件配置,组成为复杂的应用,在Spring中应用对象被声明式组合,典型地是在一个XML文件里,Spring提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了我们。

一下是重写的核心代码,首先我们需要导入spring-context的架包,一下是maven依赖

	<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>4.3.8.RELEASE</version>
		</dependency> -->

我这一导入的是4.3.8版本的目前spring框架已经更新5.0以后的版本的各位可以根据自己的需要导入自己的版本
下面是关于对象元素的获取和注入的一些代码,主要需要用到的工具是java的反射来实现的

//这里我们实现写了个ApplicationContext然后实现它 
public class ClassPathXMLApplicationContext implements ApplicationContext {
//通过键值对来获取标识符,和对象
	private Map<String,Object> container = new HashMap<>();
	
	public Map<String, Object> getContainer() {
		return container;
	}
	public void setContainer(Map<String, Object> container) {
		this.container = container;
	}
	@Override
	public Object getBean(String id) {
		return container.get(id);
	}
	//1.使用jdom读取xml文件
	//2.获取xml标签
	//3.使用反射创建对象,并且初始化,然后存入容器中去
	public ClassPathXMLApplicationContext(String path){
		SAXBuilder builder = new SAXBuilder();
		Document document = null;
		try {
		//读取xml文件
			document = builder.build(ClassPathXMLApplicationContext.class.getClassLoader().getResourceAsStream(path));
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		//获取首标签并便利标签内的元素获取bean的id及class的值
		Element root = document.getRootElement();
		List<Element> children = root.getChildren("bean");
		for(Element child : children){
		//获取id和class的value
			String key = child.getAttributeValue("id");
			String classStr = child.getAttributeValue("class");
			
			try {
			//创建对象并存入session中这里定义的是container
				Object value = Class.forName(classStr).newInstance();
				container.put(key, value);
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
		try{
		//通过循环多去对象中存储的属性以及的值然后注入
			for(Element child : children){
				Object obj = container.get(child.getAttributeValue("id"));
				List<Element> properties = child.getChildren("property");
				//先判断处理的元素是否是ref标签,如果是那么说明元素包含的是一个子对象那
				//么需要再次处理读取子对象的属性
				for(Element property : properties){
					String ref = property.getAttributeValue("ref");
					String setStr = "";
					Object value = null;
					Method setter = null;
					if(ref != null){
						setStr = "set".concat(ref.substring(0,1).toUpperCase()).concat(ref.substring(1));
						value = container.get(ref);
						setter = obj.getClass().getMethod(setStr, value.getClass().getInterfaces()[0]);
					}else{
					//如果不是对象直接通过反射获取属性及值注入对象中
						String name = property.getAttributeValue("name");
						setStr = "set".concat(name.substring(0,1).toUpperCase()).concat(name.substring(1));
						Field field = obj.getClass().getDeclaredField(name);
						
						String stringValue = property.getAttributeValue("value");
						setter = obj.getClass().getDeclaredMethod(setStr, field.getType());
						System.out.println("type : " + field.getType().getName());
						if(field.getType().getName().endsWith("Integer")) {
							Integer v = Integer.parseInt(stringValue);
							setter.invoke(obj, v);
							
						}else if(field.getGenericType().getTypeName().endsWith("String")) {
							setter.invoke(obj, stringValue);
						}
					}
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		
	}

}

以一下是ApplicationContext接口的写法

public interface ApplicationContext {
	Object getBean(String id);
}

好了以上就这些了希望这个简单demo能帮助那些不能理解ClassPathXMLApplicationContext 原理的人一点帮助。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值