复制代码
<?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"));
    }
}
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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;
}
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
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);
                    }
                }
            }
        }
    }
}