`
dyy_gusi
  • 浏览: 209552 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

Spring中BeanFacory的模拟实现(ClassPathXMLApplicationContext)

阅读更多

模拟Spring的ClassPathXMLApplicationContext类,从xml配置文件中读取然后完成bean的实例化以及bean的属性的依赖注入
1.定义配置文件

<beans>
    <bean id="user" class="com.spring.pojo.User">
        <property name="id" value="789"></property>
        <property name="name" value="cisdi"></property>
        <property name="pwd" value="123"></property>
    </bean>

    <bean id="userDao" class="com.spring.dao.impl.UserDaoImpl"></bean>
    <bean id="userService" class="com.spring.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"></property>
    </bean>
</beans>

 

2.定义一个BeanFacory接口
    这个接口的就是为了方便通过上下文获取对应的bean

public interface BeanFactory {
    public Object getBean(String beanName);
}

 

3.实现BeanFactory接口,读取配置文件,实现装配
    注意:这里使用的是jdom读取解析xml文件的方式
    关于读取解析xml文件的方式详见:http://dyygusi.iteye.com/blog/1996153

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

public class MyClassPathXMLApplicationContext implements BeanFactory {

    //所有被容器管理的bean都放在这个map中,当解析完xml以后,所有的bean都放在了这个集合中
    private Map<String, Object> beans = new HashMap<String, Object>();

    @SuppressWarnings("unchecked")
    public MyClassPathXMLApplicationContext(String xmlPath) {
        xmlPath = "E:\\XNYY\\webSpring_\\src\\" + xmlPath;
        SAXBuilder builder = new SAXBuilder(false);// 用来读取xml文件
        Document document;// 构建一个文档对象,用来将xml转换成Document对象
        try {
            document = builder.build(new FileInputStream(new File(xmlPath)));// 从给定的文件中读取xml并且构建成Document
            Element elementRoot = document.getRootElement();// 获得文档对象的根节点

            List<Element> elementList = elementRoot.getChildren("bean");// 获得根节点下面所有的bean节点
            for (Element e : elementList) {// 遍历bean节点
                Element element = e;// 当前的bean节点
                String id = element.getAttribute("id").getValue();// bean的id
                String clazzStr = element.getAttribute("class").getValue();// bena的class
                Class clazz = Class.forName(clazzStr);// 通过反射,得到bean的class的Class
                Object clazzObj = clazz.newInstance();// 获得一个class对应的实例
                beans.put(id, clazzObj);// 将bean的id和class放入map集合中
                List<Element> propertyElementList = element.getChildren("property");// 得到bean下所有的property元素
                for (Element property : propertyElementList) {// 遍历所有的property元素节点
                    String name = property.getAttributeValue("name");// 得到property的name
                    Object valueObj = null;// perperty的name对应的object

                    Method[] methods = clazz.getMethods();// 得到class下所有的方法

                    // 如果需要注入的是基本类型包括String
                    String valueStr = property.getAttributeValue("value");
                    if (valueStr != null) {
                        valueObj = valueStr;
                        for (Method method : methods) {// 遍历所有的方法
                            String methodName = method.getName();// 方法名称
                            Class[] types = method.getParameterTypes();// 方法参数类型
                            // 找到对应的setXxx方法
                            if (methodName.contains("set") && methodName.toUpperCase().contains(name.toUpperCase())) {
                                Class parameterType = types[0];// 得到setXxx方法参数类型
                                // 如果是Integer类型
                                if (parameterType == Integer.class) {
                                    method.invoke(clazzObj, Integer.parseInt(valueStr));
                                } else {// 如果是String类型
                                    method.invoke(clazzObj, valueStr);
                                }
                            }
                        }
                    }

                    // 如果注入的是引用类型
                    String refStr = property.getAttributeValue("ref");
                    if (refStr != null) {
                        valueObj = beans.get(refStr);// 在map中取出对应的引用对象
                        for (Method m : methods) {
                            String methodName = m.getName();
                            if (methodName.contains("set") && methodName.toUpperCase().contains(name.toUpperCase())) {
                                // 得到对应的方法,第二个参数是method方法的参数类型,是一个接口类型
                                Method method = clazz.getMethod(methodName, valueObj.getClass().getInterfaces()[0]);
                                method.invoke(clazzObj, valueObj);
                            }
                        }
                    }

                }
            }
        } catch (JDOMException | IOException | ClassNotFoundException | InstantiationException | IllegalAccessException
                | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException e) {
            e.printStackTrace();
        }

    }

    @Override
    public Object getBean(String beanName) {
        return beans.get(beanName);
    }

}

 

4.测试MyClassPathXMLApplicationContext

@Test
public void testMyApplication() {
    BeanFactory context = new MyClassPathXMLApplicationContext("My-application-context.xml");//初始化容器
    UserService userService = (UserService) context.getBean("userService");//从容器里面得到UserService
    User user = (User) context.getBean("user");//得到User对象
    userService.addUser(user);//通过Service将得到的User对象存入数据库
}

 

5.其他代码:
    User.java(pojo)
    UserDao.java(dao)
    UserService.java(service)

2
0
分享到:
评论

相关推荐

    模拟spring中的ClassPathXmlApplicationContext类的实现

    在Spring中,`ClassPathXmlApplicationContext`是用于加载和管理配置元数据的一个重要类,它允许我们通过XML配置文件来创建和初始化bean。这个类在启动Spring应用上下文时起着关键作用。 `...

    spring容器的触发事件 ClassPathXmlApplicationContext的start()方法的用法

    示例代码中定义了一个简单的 Spring 应用程序,通过 `ClassPathXmlApplicationContext` 来初始化一个 Spring 容器,并注册了一些事件监听器。 ```java package ioc.test; import org.springframework.context....

    spring为ApplicationContext提供的3种实现分别为:ClassPathXmlApplicationContext

    在 Spring 中,ApplicationContext 是一个至关重要的接口,它是应用上下文的实现,负责管理bean的生命周期和装配。标题提到的“ClassPathXmlApplicationContext”是 Spring 提供的三种 ApplicationContext 实现之一...

    利用spring实现打印机

    接下来,我们将利用Spring的XML配置文件来声明`LaserPrinter`为`Printer`接口的实现,并注入到需要使用打印机的类中。在`beans.xml`配置文件中,我们这样定义: ```xml ``` 然后,假设我们有一个`DocumentService...

    Spring简单底层实现

    ### Spring框架底层实现详解 #### 一、Spring框架如何创建实例 在深入探讨Spring框架的底层实现机制之前,我们先来了解一下Spring框架的基本概念。Spring框架是一个开源的应用框架,主要目的是简化企业级应用的...

    spring的基础(一)自己写的ClassPathXmlApplicationContext类

    在本篇博文中,我们将深入探讨Spring框架的基础知识,特别是关注如何自己编写一个`ClassPathXmlApplicationContext`类。`ClassPathXmlApplicationContext`是Spring框架中用于加载和管理配置元数据的核心类,它允许...

    Spring使用与实现总结.pdf

    - **Resource**是Spring中对外部资源的抽象,主要用于文件的抽象,尤其是XML文件,其中通常包含了Spring用户的Bean定义。 - **Resource**接口提供了一套比Java标准的URL访问机制更为灵活和强大的机制,支持多种资源...

    手写SpringIoc的XML实现方式

    在本主题中,我们将深入探讨如何手写一个基于XML的Spring IOC实现,模仿Spring框架中的`ClassPathXmlApplicationContext`。这个实现旨在帮助理解Spring底层的工作原理,并加深对IoC容器的理解。 首先,我们需要创建...

    Spring-Reference_zh_CN(Spring中文参考手册)

    6.8.1. 在Spring中使用AspectJ来为domain object进行依赖注入 6.8.1.1. @Configurable object的单元测试 6.8.1.2. 多application context情况下的处理 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来...

    Spring通过xml实现IOC

    在早期版本的Spring中,DI主要通过XML配置文件来实现,这就是所谓的Inversion of Control Container(控制反转容器),也就是IOC。本文将深入探讨Spring如何通过XML配置实现IOC,以及其背后的原理和应用。 首先,...

    Spring获取ApplicationContext对象工具类的实现方法

    在Spring中,典型的获取ApplicationContext对象的方式是使用ApplicationContext接口的一个实现类,如ClassPathXmlApplicationContext。这是一个根据给定XML文件的类路径的上下文实现。通常我们会在初始化Spring IoC...

    简单Spring容器实现

    在IT行业中,Spring框架是Java应用开发中的一个关键组件,尤其在企业级应用中广泛使用。本主题将深入探讨“简单Spring容器实现”,基于提供的标签“源码”和“工具”,我们将聚焦于Spring容器的原理及其简易实现。...

    在非spring注解类中使用spring容器中的bean_普通类中使用yml配置文件中的配置信息

    然而,在某些情况下,我们可能需要在非Spring注解的类中访问Spring容器中的Bean,或者在这些类中使用YAML配置文件中的配置信息。本篇将详细介绍如何在这样的场景下实现这一目标。 首先,让我们来理解如何在非Spring...

    如何在spring中等价配置得到原本由jndi配置实现的数据源

    以下是如何在Spring中进行这种转换的详细步骤和知识点: 1. **理解JNDI配置**: JNDI是一种标准服务,用于在分布式环境中查找和绑定对象。在Web应用中,数据源可以通过JNDI名字在全局命名空间中注册,然后应用通过...

    Spring2.5 IOC的简单实现

    以下将详细讲解 Spring 2.5 中的 IOC 实现原理以及如何创建简单的应用。 **1. IOC 简介** IOC 是一种设计模式,它将对象的创建和管理交给容器处理,使得代码更加松耦合。Spring 框架通过 XML 配置文件或注解方式来...

    Spring中ApplicationContext加载机制

    Spring中ApplicationContext加载机制 ApplicationContext 是 Spring 框架中的核心组件之一,负责加载和管理应用程序中的 Bean 对象。在 Web 应用程序中,ApplicationContext 的加载机制是非常重要的, Spring 提供...

    使用Spring2.5的Autowired实现注释型的IOC

    在 Spring 2.5 中,Autowired 是一个非常重要的特性,它可以实现快速的自动注入,无需在 XML 文档里面添加 bean 的声明,大大减少了 XML 文档的维护。下面我们将详细介绍如何使用 Spring 2.5 的 Autowired 实现注释...

    Spring中使用classpath加载配置文件浅析

    在Spring中,可以通过ApplicationContext接口的实现类,比如ClassPathXmlApplicationContext,来加载位于classpath中的配置文件。例如,创建一个ApplicationContext对象的代码如下: ```java ApplicationContext ...

    Spring IOC实现原理demo

    在本文中,我们将深入探讨Spring IOC的实现原理,并通过一个简单的示例来展示其工作流程。 首先,我们需要理解什么是控制反转。在传统的编程模式中,程序员手动创建并管理对象,而Spring IOC则将这种控制权反转,由...

Global site tag (gtag.js) - Google Analytics