该容器需要借助于Dom4jJar包来解析XML文件。
1.
package com.lanp.myioc;
/**
* 输出接口
* @author LanP
*/
public interface Output {
/**
* 获取输出消息
* @param msg
* @return String
*/
String getMsg(String msg);
void out();
}
2.
package com.lanp.myioc;
/**
* 带缓存的打印机
* @author LanP
*/
public class BuffPrinter implements Output {
private static final int MAX_SIZE = 1024;
private StringBuffer[] printMsg = new StringBuffer[MAX_SIZE * 2];
/**
* 记录当前打印的作用位置
*/
private int msgNum = 0;
@Override
public String getMsg(String msg) {
if(msgNum >= MAX_SIZE){
System.out.println("输出管道队列已满,添加失败!");
} else {
printMsg[msgNum++] = new StringBuffer(msg);
}
return msg;
}
@Override
public void out() {
//只要尚有作用没有打印就继续打印
while(msgNum > 0) {
System.out.println("缓存打印机打印: " + printMsg[0].toString());
//将作业队列向前移一位,剩下的作业书量减一
System.arraycopy(printMsg, 1, printMsg, 0, --msgNum);
}
}
}
3.
package com.lanp.myioc;
/**
* 普通打印机类,实现了输出接口
* @author LanP
*/
public class Printer implements Output {
private static final int MAX_SIZE = 1024;
private String[] printMsg = new String[MAX_SIZE];
/**
* 记录当前打印的作用位置
*/
private int msgNum = 0;
@Override
public String getMsg(String msg) {
if(msgNum >= MAX_SIZE){
System.out.println("输出管道队列已满,添加失败!");
} else {
printMsg[msgNum++] = msg;
}
return msg;
}
@Override
public void out() {
//只要尚有作用没有打印就继续打印
while(msgNum > 0) {
System.out.println("普通打印机打印: " + printMsg[0]);
//将作业队列向前移一位,剩下的作业书量减一
System.arraycopy(printMsg, 1, printMsg, 0, --msgNum);
}
}
}
4.
package com.lanp.myioc;
/**
* 计算机实例,具有打印机
* @author LanP
* @version V1.0
*/
public class Computer {
private String name;
public void setName(String name) {
this.name = name;
}
private Output output;
public void setOutput(Output output) {
this.output = output;
}
public Computer() {
}
public Computer(Output output) {
this.output = output;
}
/**
* 模拟消息输入的方法
* @param msg
*/
public void msgIn(String msg) {
this.output.getMsg(msg);
}
/**
* 模拟打印
*/
public void print() {
output.out();
}
}
5.
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="computer" class="com.lanp.myioc.Computer">
<property name="name" value="飘飘电脑" />
<property name="output" ref="buffPrinter" />
</bean>
<bean id="printer" class="com.lanp.myioc.Printer"/>
<bean id="buffPrinter" class="com.lanp.myioc.BuffPrinter"/>
<bean id="nowtime" class="java.util.Date" scope="prototype" />
</beans>
6.
package com.lanp.myioc;
/**
* 应用程序容器接口
* @author LanP
*/
public interface MyApplicationContext {
/**
* 获取指定Bean实例的方法
* @param name
* @return Object
* @throws Exception
*/
Object getBean(String name) throws Exception;
}
7.
package com.lanp.myioc;
import java.io.File;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
/**
* 应用程序上下文容器实现类
* @author LanP
* @version V1.0
*/
public class MyXmlApplicationContext implements MyApplicationContext {
/**
* 保存容器中所以单例模式的Bean实例
*/
private Map<String,Object> objPool = Collections.synchronizedMap(new HashMap<String,Object>());
/**
* 保存配置文件对于的Document对象
*/
private Document document;
/**
* 保存配置文件中的根元素
*/
private Element root;
public MyXmlApplicationContext(String filePath) throws Exception {
SAXReader reader = new SAXReader();
document = reader.read(new File(filePath));
root = document.getRootElement();
initPool();
initProp();
}
/**
* 初始化容器中的属性
* @throws Exception
*/
@SuppressWarnings("unchecked")
private void initProp() throws Exception {
//遍历配置文件里的每个<bean>标签
for(Object obj:root.elements()) {
Element beanElement = (Element)obj;
//取得bean元素中的ID
String beanId = beanElement.attributeValue("id");
//取得bean元素中的scope
String beanScope = beanElement.attributeValue("scope");
//如果Bean标签中的scope不存在或为singleton
if(null == beanScope || beanScope.equals("singleton")) {
//取出objPool中的bean实例
Object bean = objPool.get(beanId);
//遍历Bean元素中的每个property
for(Object prop: beanElement.elements()) {
Element propElement = (Element)prop;
//取得property元素的name
String propName = propElement.attributeValue("name");
//取得property元素的value
String propValue = propElement.attributeValue("value");
//取得property元素的ref
String propRef = propElement.attributeValue("ref");
//将属性名首字母大写
String propNameUpCase = propName.substring(0,1).toUpperCase()
+ propName.substring(1, propName.length());
//如果property元素的value存在
if(null != propValue && propValue.length() > 0) {
//获取设置注入的set方法
Method setter = bean.getClass().getMethod("set" + propNameUpCase, String.class);
//执行set注入
setter.invoke(bean, propValue);
}
if(null != propRef && propRef.length() > 0) {
//取出需要依赖注入的bean实例
Object target = objPool.get(propRef);
//objPool不存在指定的实例
if(null == target) {
System.out.println("不存在你要注入的bean实例");
}
//定义设值注入所需的set方法
Method setter = null;
//遍历target对象实现的所有接口
for(Class superInterface : target.getClass().getInterfaces()) {
try {
//获取设值注入所需的setter方法
setter = bean.getClass().getMethod("set" + propNameUpCase,superInterface);
//如果成功获得该接口对应的方法,直接跳出循环
break;
} catch (Exception e) {
//如果没有找到对应的setter方案,继续下次循环
continue;
}
}
//如果setter方法依然为null
//则直接获得target实现类对应的setter方法
if(null == setter) {
setter = bean.getClass().getMethod("set" + propNameUpCase, target.getClass());
}
//执行setter注入
setter.invoke(bean, target);
}
}
}
}
}
/**
* 初始化容器中所有的单例bean
* @throws Exception
*/
private void initPool() throws Exception {
//遍历配置文件里面的每个<bean>标签
for(Object obj:root.elements()) {
Element beanElement = (Element)obj;
//取得Bean元素的Id
String beanId = beanElement.attributeValue("id");
//取得Bean元素的class
String beanClass = beanElement.attributeValue("class");
//取得bean元素的scope
String beanScope = beanElement.attributeValue("scope");
if(null == beanScope || beanScope.equals("singleton")) {
//模拟构造器创建Bean实例,并将其实例放进objPool
objPool.put(beanId, Class.forName(beanClass).newInstance());
} else {
//对于非单例的配置,将其bean类名放进objPool
objPool.put(beanId, beanClass);
}
}
}
/**
* 获取bean实例
*/
@Override
public Object getBean(String name) throws Exception {
Object target = objPool.get(name);
//对于单例bean,容器已经初始化了所有bean实例
if(target.getClass() != String.class) {
return target;
} else {
String clazz = (String)target;
//对于prototype并未注入属性值
return Class.forName(clazz).newInstance();
}
}
}
8.
package com.lanp.myioc;
public class MyIocTest {
/**
* 容器工厂的测试类
* @param args
*/
public static void main(String[] args) throws Exception {
//创建IOC容器
MyApplicationContext myApplicationContext = new MyXmlApplicationContext("D:\\lanp\\lanp\\eclipse\\my_workspace\\MyDesModPro\\src\\com\\lanp\\myioc\\bean.xml");
//从IOC容器中取出Computer Bean
Computer computer = (Computer)myApplicationContext.getBean("computer");
//测试Computer对象
computer.msgIn("飘");
computer.msgIn("飘飘");
computer.print();
System.out.println(myApplicationContext.getBean("nowtime"));
}
}