编码剖析Spring管理Bean的原理

来源:互联网 发布:卡尔维诺 知乎 编辑:程序博客网 时间:2024/06/04 08:33

在Spring的第一个案例中,我们已经知道了怎么将bean交给Spring容器进行管理,并且明白了怎么从Spring容器中获取bean。那我们就有一个疑问了:Spring是如何创建并管理bean的呢?现在我们就来编码剖析Spring管理Bean的原理。
本文是在Spring的第一个案例的基础上展开的。
我们要使用dom4j读取Sping的配置文件——beans.xml

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd">    <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean"></bean></beans>

那么就需要将dom4j所需的jar包导入该项目中。dom4j所需的jar包为:

  • dom4j-1.6.1.jar
  • jaxen-1.1-beta-6.jar

dom4j读取到诸如

<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean"></bean>

这样的内容时,务必需要将读取到的bean的信息存到一个JavaBean对象中。于是我们可在junit.test包下创建这样一个JavaBean——BeanDefinition.java,其代码为:

/** * 将读取到的bean的信息存到一个JavaBean对象中 * @author li ayun * */public class BeanDefinition {    private String id;    private String className;    public BeanDefinition(String id, String className) {        this.id = id;        this.className = className;    }    public String getId() {        return id;    }    public void setId(String id) {        this.id = id;    }    public String getClassName() {        return className;    }    public void setClassName(String className) {        this.className = className;    }}

接下来我们就创建一个传智播客版的Spring容器来模拟Spring容器。在junit.test下新建一个类——ItcastClassPathXMLApplicationContext.java,其代码如下:

/** * 传智播客版Spring容器 * @author li ayun * */public class ItcastClassPathXMLApplicationContext {    private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();    private Map<String, Object> sigletons = new HashMap<String, Object>();    public ItcastClassPathXMLApplicationContext(String filename) {        this.readXML(filename);        this.instanceBeans();    }    /**     * 完成bean的实例化     */    private void instanceBeans() {        for (BeanDefinition beanDefinition : beanDefines) {            try {                if (beanDefinition.getClassName() != null && !"".equals(beanDefinition.getClassName().trim())) {                    sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance());                }            } catch (Exception e) {                e.printStackTrace();            }        }    }    /**     * 读取XML配置文件     * @param filename     */    private void readXML(String filename) {        SAXReader saxReader = new SAXReader();        Document document = null;        try {            URL xmlpath = this.getClass().getClassLoader().getResource(filename);            document = saxReader.read(xmlpath);            Map<String, String> nsMap = new HashMap<String, String>();            nsMap.put("ns", "http://www.springframework.org/schema/beans"); // 加入命名空间            XPath xsub = document.createXPath("//ns:beans/ns:bean"); // 创建beans/bean查询路径            xsub.setNamespaceURIs(nsMap); // 设置命名空间            List<Element> beans = xsub.selectNodes(document); // 获取文档下所有bean节点            for (Element element : beans) {                String id = element.attributeValue("id"); // 获取id属性值                String clazz = element.attributeValue("class"); // 获取class属性值                BeanDefinition beanDefine = new BeanDefinition(id, clazz);                beanDefines.add(beanDefine);            }        } catch (Exception e) {            e.printStackTrace();        }    }    /**     * 获取bean实例     * @param beanName     * @return     */    public Object getBean(String beanName) {        return this.sigletons.get(beanName);    }}

这样,传智播客版的Spring容器就创建出来了。接下来我们就要测试传智播客版的Spring容器是否能够取得bean实例,只须修改SpringTest类的代码为:

public class SpringTest {    @Test    public void test() {        // ApplicationContext是接口        // ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); // 实例化Spring容器        // PersonService personService = (PersonService) ctx.getBean("personService"); // 从Spring容器取得bean        // personService.save();        ItcastClassPathXMLApplicationContext ctx = new ItcastClassPathXMLApplicationContext("beans.xml"); // 实例化Spring容器        PersonService personService = (PersonService) ctx.getBean("personService"); // 从Spring容器取得bean        personService.save();    }}

测试test()方法,Eclipse控制台打印如下:
这里写图片描述
通过编写代码剖析Spring管理Bean的原理,我们就能深刻理解Spring内部到底是如何创建并管理bean实例的。源码可点击编码剖析Spring管理Bean的原理进行下载。

0 0
原创粉丝点击