<?xml version="1.0" encoding="GBK"?>
<beans>
<bean id="computer" class="lee.Computer">
<!-- 为name注入基本类型的值 -->
<property name="name" value="孙悟空的电脑"/>
<!-- 为out注入容器中其他Bean -->
<property name="out" ref="betterPrinter"/>
</bean>
<!-- 配置两个Bean实例 -->
<bean id="printer" class="lee.Printer"/>
<bean id="betterPrinter" class="lee.BetterPrinter"/>
<!-- 配置一个prototype行为的Bean实例 -->
<bean id="now" class="java.util.Date" scope="prototype"/> <!--①-->
</beans>
<?xml version="1.0" encoding="GBK"?>
<project name="hibernte" basedir="." default="">
<property name="src" value="src"/>
<property name="dest" value="classes"/>
<path id="classpath">
<fileset dir="lib">
<include name="*.jar"/>
</fileset>
<pathelement path="${dest}"/>
</path>
<target name="compile" description="Compile all source code">
<delete dir="${dest}"/>
<mkdir dir="${dest}"/>
<copy todir="${dest}">
<fileset dir="${src}">
<exclude name="**/*.java"/>
</fileset>
</copy>
<javac destdir="${dest}" debug="true"
deprecation="false" optimize="false" failonerror="true">
<src path="${src}"/>
<classpath refid="classpath"/>
</javac>
</target>
<target name="run" description="Run the main class" depends="compile">
<java classname="lee.IoCTest" fork="yes" failonerror="true">
<classpath refid="classpath"/>
</java>
</target>
</project>
package lee;
/**
* Description:
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br/>Copyright (C), 2001-2016, Yeeku.H.Lee
* <br/>This program is protected by copyright laws.
* <br/>Program Name:
* <br/>Date:
* @author Yeeku.H.Lee kongyeeku@163.com
* @version 1.0
*/
public class BetterPrinter implements Output
{
private String[] printData = new String[MAX_CACHE_LINE * 2];
// 用以记录当前需打印的作业数
private int dataNum = 0;
public void out()
{
// 只要还有作业,继续打印
while(dataNum > 0)
{
System.out.println("高速打印机正在打印:" + printData[0]);
// 把作业队列整体前移一位,并将剩下的作业数减1
System.arraycopy(printData , 1, printData, 0, --dataNum);
}
}
public void getData(String msg)
{
if (dataNum >= MAX_CACHE_LINE * 2)
{
System.out.println("输出队列已满,添加失败");
}
else
{
// 把打印数据添加到队列里,已保存数据的数量加1。
printData[dataNum++] = msg;
}
}
}
package lee;
/**
* Description:
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br/>Copyright (C), 2001-2016, Yeeku.H.Lee
* <br/>This program is protected by copyright laws.
* <br/>Program Name:
* <br/>Date:
* @author Yeeku.H.Lee kongyeeku@163.com
* @version 1.0
*/
public class Computer
{
private Output out;
private String name;
public Computer(){}
// out的setter和getter方法
public void setOut(Output out)
{
this.out = out;
}
// name的setter和getter方法
public void setName(String name)
{
this.name = name;
}
// 定义一个模拟获取字符串输入的方法
public void keyIn(String msg)
{
out.getData(msg);
}
// 定义一个模拟打印的方法
public void print()
{
System.out.println(name + "开始打印...");
out.out();
}
}
package lee;
import org.crazyit.ioc.*;
/**
* Description:
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br/>Copyright (C), 2001-2016, Yeeku.H.Lee
* <br/>This program is protected by copyright laws.
* <br/>Program Name:
* <br/>Date:
* @author Yeeku.H.Lee kongyeeku@163.com
* @version 1.0
*/
public class IoCTest
{
public static void main(String[] args)
throws Exception
{
// 创建IoC容器
ApplicationContext ctx = new CrazyitXmlApplicationContext("beans.xml");
// 从IoC容器中取出computer Bean
Computer c = (Computer)ctx.getBean("computer");
// 测试Computer对象
c.keyIn("轻量级Java EE企业应用实战");
c.keyIn("疯狂Java讲义");
c.print();
System.out.println(ctx.getBean("now"));
}
}
package lee;
/**
* Description:
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br/>Copyright (C), 2001-2016, Yeeku.H.Lee
* <br/>This program is protected by copyright laws.
* <br/>Program Name:
* <br/>Date:
* @author Yeeku.H.Lee kongyeeku@163.com
* @version 1.0
*/
public interface Output
{
// 接口里定义的属性只能是常量
int MAX_CACHE_LINE = 50;
// 接口里定义的只能是public的抽象实例方法
void out();
void getData(String msg);
}
package lee;
/**
* Description:
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br/>Copyright (C), 2001-2016, Yeeku.H.Lee
* <br/>This program is protected by copyright laws.
* <br/>Program Name:
* <br/>Date:
* @author Yeeku.H.Lee kongyeeku@163.com
* @version 1.0
*/
// 让Printer类实现Output
public class Printer implements Output
{
private String[] printData = new String[MAX_CACHE_LINE];
// 用以记录当前需打印的作业数
private int dataNum = 0;
public void out()
{
// 只要还有作业,继续打印
while(dataNum > 0)
{
System.out.println("打印机打印:" + printData[0]);
// 把作业队列整体前移一位,并将剩下的作业数减1
System.arraycopy(printData , 1, printData, 0, --dataNum);
}
}
public void getData(String msg)
{
if (dataNum >= MAX_CACHE_LINE)
{
System.out.println("输出队列已满,添加失败");
}
else
{
// 把打印数据添加到队列里,已保存数据的数量加1。
printData[dataNum++] = msg;
}
}
}
package org.crazyit.ioc;
/**
* Description:
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br/>Copyright (C), 2001-2016, Yeeku.H.Lee
* <br/>This program is protected by copyright laws.
* <br/>Program Name:
* <br/>Date:
* @author Yeeku.H.Lee kongyeeku@163.com
* @version 1.0
*/
public interface ApplicationContext
{
// 获取指定Bean实例的方法
Object getBean(String name)
throws Exception;
}
package org.crazyit.ioc;
import java.lang.reflect.*;
import java.util.*;
import java.io.*;
import org.dom4j.*;
import org.dom4j.io.*;
/**
* Description:
* <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
* <br/>Copyright (C), 2001-2016, Yeeku.H.Lee
* <br/>This program is protected by copyright laws.
* <br/>Program Name:
* <br/>Date:
* @author Yeeku.H.Lee kongyeeku@163.com
* @version 1.0
*/
public class CrazyitXmlApplicationContext
implements ApplicationContext
{
// 保存容器中所有单例模式的Bean实例
private Map<String , Object> objPool
= Collections.synchronizedMap(new HashMap<String , Object>());
// 保存配置文件对应的Document对象
private Document doc;
// 保存配置文件里的根元素
private Element root;
public CrazyitXmlApplicationContext(String filePath)
throws Exception
{
SAXReader reader = new SAXReader();
doc = reader.read(new File(filePath));
root = doc.getRootElement();
initPool();
initProp();
}
public Object getBean(String name)
throws Exception
{
Object target = objPool.get(name);
// 对于singleton Bean,容器已经初始化了所有Bean实例,直接返回即可
if (target.getClass() != String.class)
{
return target;
}
else
{
String clazz = (String)target;
// 对于prototype对象并未注入属性值
return Class.forName(clazz).newInstance();
}
}
// 初始化容器中所有singleton Bean
private void initPool()
throws Exception
{
// 遍历配置文件里的每个<bean.../>元素
for (Object obj : root.elements())
{
Element beanEle = (Element)obj;
// 取得<bean.../>元素的id属性
String beanId = beanEle.attributeValue("id");
// 取得<bean.../>元素的class属性
String beanClazz = beanEle.attributeValue("class");
// 取得<bean.../>元素的scope属性
String beanScope = beanEle.attributeValue("scope");
// 如果<bean.../>元素的scope属性不存在,或为singleton
if (beanScope == null ||
beanScope.equals("singleton"))
{
// 以默认构造器创建Bean实例,并将其放入objPool中
objPool.put(beanId , Class.forName(beanClazz).newInstance());
}
else
{
// 对于非singlton Bean,存放该Bean实现类的类名。
objPool.put(beanId , beanClazz);
}
}
}
// 初始化容器中singleton Bean的属性
private void initProp()
throws Exception
{
// 遍历配置文件里的每个<bean.../>元素
for (Object obj : root.elements())
{
Element beanEle = (Element)obj;
// 取得<bean.../>元素的id属性
String beanId = beanEle.attributeValue("id");
// 取得<bean.../>元素的scope属性
String beanScope = beanEle.attributeValue("scope");
// 如果<bean.../>元素的scope属性不存在,或为singleton
if (beanScope == null ||
beanScope.equals("singleton"))
{
// 取出objPool的指定的Bean实例
Object bean = objPool.get(beanId);
// 遍历<bean.../>元素的每个<property.../>子元素
for (Object prop : beanEle.elements())
{
Element propEle = (Element)prop;
// 取得<property.../>元素的name属性
String propName = propEle.attributeValue("name");
// 取得<property.../>元素的value属性
String propValue = propEle.attributeValue("value");
// 取得<property.../>元素的ref属性
String propRef = propEle.attributeValue("ref");
// 将属性名的首字母大写
String propNameCamelize = propName.substring(0 , 1)
.toUpperCase() + propName.substring(1 , propName.length());
// 如果<property.../>元素的value属性值存在
if (propValue != null && propValue.length() > 0)
{
// 获取设值注入所需的setter方法
Method setter = bean.getClass().getMethod(
"set" + propNameCamelize , String.class);
// 执行setter注入
setter.invoke(bean , propValue);
}
if (propRef != null && propRef.length() > 0)
{
// 取得需要被依赖注入的Bean实例
Object target = objPool.get(propRef);
//objPool池中不存在指定Bean实例
if (target == null)
{
// 此处还应处理Singleton Bean依赖prototype Bean的情形
}
// 定义设值注入所需的setter方法
Method setter = null;
// 遍历target对象所所实现的所有接口
for (Class superInterface : target.getClass().getInterfaces())
{
try
{
// 获取设值注入所需的setter方法
setter = bean.getClass().getMethod(
"set" + propNameCamelize , superInterface);
// 如果成功取得该接口对应的方法,直接跳出循环
break;
}
catch (NoSuchMethodException ex)
{
// 如果没有找到对应的setter方法,继续下次循环
continue;
}
}
// 如果setter方法依然为null,
// 则直接取得target实现类对应的setter方法
if (setter == null)
{
setter = bean.getClass().getMethod(
"set" + propNameCamelize , target.getClass());
}
// 执行setter注入
setter.invoke(bean , target);
}
}
}
}
}
}