热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

spring原理1:java模拟springIOC容器

本篇博客主要是使用java代码模拟spring的IOC容器,实现依赖注入;当然只是模拟spring容器中简单的一点实现原理而已,加深一些自己对spring框架的底层原理的理解;使用

本篇博客主要是使用java代码模拟spring的IOC容器,实现依赖注入;当然只是模拟spring容器中简单的一点实现原理而已,加深一些自己对spring框架的底层原理的理解;

使用的技术:dom4j xml解析技术   工厂模式    java反射技术

关于工厂模式:主要作用是对象的的解耦,通过容器中的方法获取对象,而不是在需要的类中去 new 对象;针对接口编程,不需要关注具体的实现方式;

如:一个对象:Car 依赖的对象有 Engine   Wheel  Door

不用工厂模式此时如果需要创建Car,则需要在Car 对象中 创建 Engine   Wheel  Door 三个对象,这样的弊端是在代码中耦合了太多其他的对象:此时如果Engine 对象和 Wheel对象改变了属性,那么调用者在调用时也需要做修改;如果依赖的对象很多的话,对于调用者是一件很麻烦的事情;

public class Car implements ICar{

	private Engine engine;
	private Wheel wheel;
	private Door door;
	public Car(Engine engine, Wheel wheel, Door door) {
		super();
		this.engine = engine;
		this.wheel = wheel;
		this.door = door;
	}
	
	public static void main(String[] args) {
		Engine engine=new Engine();
		 Wheel wheel=new Wheel();
		 Door door=new Door();
		 
		Car car=new Car(new Engine(), new Wheel(), new Door());
	}
}

此时就引入了工厂模式:

Car的工厂类如下所示:

public class Factory implements Ifactory{

    @Override
    public Car createCar() {
        Engine engine=new Engine();
        Wheel wheel=new Wheel();
        Door door=new Door();
        return new Car(engine, wheel, door);
    }
}

 调用者需要Car的对象的时候只需要调用工厂类的  createCar() 方法即可:这是就算有依赖的类更改了属性或者方法,对于调用方而言可以不做任何更改;

public static void main(String[] args) {
        Factory f=new Factory();
        ICar car=f.createCar();
    }

当然,这样并不完美:试想一个场景:Engine 有 大众的 丰田的   Wheel 也有大众和丰田的  Door 也分为大众和丰田的,现在调用方需要的是大众的Car

那么在工厂类中就需要更改为大众类,如果有上千个品牌,那么工厂类的维护也是一件很痛苦的事,这是引入统一接口,接口的引用指向具体的实现类,具体的实现由调用方指定,这样就减少了代码的耦合;

但是,基于接口的工厂模式还是不完美,这种方式:我需要在工厂类中 new 对象 并且需要通过构造器或者是set方法把需要注入的对象注入进来,此时,试想一个场景:如果你有100个对象需要被其他对象注入,那么这个工厂类则需要维护100 个方法来返回对象;工厂类的维护一件很复杂的任务;

这是可以想到用配置文件来管理这些类的名称,然后在工厂类中通过在配置文件中的类的名称实现类的创建和注入;这样需要增删改工厂类的创建对象则可以通过更改配置文件来实现,这样就方便了很多;

这就是一种比较完美的实现方式:IOC模式;

下面通过java代码来实现ioc模式:

mydoc.xml的配置如下:

 
     
          
    
    
     
    
 

userService的接口代码:

public interface UserService {

    public void getUser();
}

实现代码如下:

public class UserServiceImpl implements UserService{

        @Override
    public void getUser() {
        System.out.println("i am beppe!!");

    }

    
}    

UserController的代码如下

public class UserController {

    private UserService userService;
    
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void getUser(){
        userService.getUser();
//        System.out.println(user.getName());
    }
    
    public void say(){
        System.out.println("say something");
    }
}

下面模拟spring 的Ioc来实现最基本的依赖注入:

工厂接口如下:BeanFactory  这个接口不做任何的实现,只有一个getBean(String id) 的方法 具体的具体的工厂类需要实现这个接口,并且覆盖相应的方法:

public interface BeanFactory {

    public Object getBean(String id);
}

以下为BeanFatory的具体实现类;IOC容器的关键,实现依赖注入;这里用一个Map容器来存储对象,并且可以通过key来获取对象

public class ClassPathXmlApplicationContext implements BeanFactory{

    private Map beans=new HashMap();     //创建容器,用来存储需要被IOC容器管理的对象
    
//    构造该容器时就初始化beans的值
    public ClassPathXmlApplicationContext(String filePath){          //在创建工厂对象的时候就将需要被管理的对存放到map中
        Document doc = getDocument(filePath);                        //解析 xml 文件
        Element rootElement = doc.getRootElement();
        List beanElements = rootElement.elements();      
        for (Element beanElement : beanElements) {                    //获取bean 标签 并且实例化对象
            String idStr = beanElement.attributeValue("id");
            String classStr=beanElement.attributeValue("class");
            System.out.println(idStr+":"+classStr);
            try {
                Class clazz = Class.forName(classStr);
                Object obj = clazz.newInstance();
                beans.put(idStr, obj);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            

        }
        
        for (Element beanElement1 : beanElements) {
            List propertyElements = beanElement1.elements();
            for (Element propertyElement : propertyElements) {              //获取 标签下的所有property标签  并且 通过调用set方法来进行注入:关键的方法
                Element parentElement=propertyElement.getParent();
                Object contoller=getBean(parentElement.attributeValue("id"));
                String nameStr = propertyElement.attributeValue("name");
                String refStr=propertyElement.attributeValue("ref");
                Object service = getBean(refStr);
                String methodStr="set"+nameStr.substring(0, 1).toUpperCase()+nameStr.substring(1);
                try {
                    Method method=contoller.getClass().getMethod(methodStr, service.getClass().getInterfaces()[0]);
                    method.invoke(contoller, service);
                }  catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
            
        }
    }
    
    @Override
    public Object getBean(String id) {
        // TODO Auto-generated method stub
        return beans.get(id);
    }
    
    private Document getDocument(String filePath){
        try {
//            URL url=new URL(filePath);
            SAXReader redaer=new SAXReader();
            Document doc = redaer.read(filePath);
            return doc;
        } catch (DocumentException e) {
            // TODO Auto-generated catch block
            System.out.println("路径不存在");
            e.printStackTrace();
        }
        return null;
    }
}

这就是一个简单的spring IOC容器,当然,功能远没有spring IOC那么强大,基本的实现原理是一致的;

 


推荐阅读
  • 如何查询zone下的表的信息
    本文介绍了如何通过TcaplusDB知识库查询zone下的表的信息。包括请求地址、GET请求参数说明、返回参数说明等内容。通过curl方法发起请求,并提供了请求示例。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • 本文介绍了在go语言中利用(*interface{})(nil)传递参数类型的原理及应用。通过分析Martini框架中的injector类型的声明,解释了values映射表的作用以及parent Injector的含义。同时,讨论了该技术在实际开发中的应用场景。 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • Spring学习(4):Spring管理对象之间的关联关系
    本文是关于Spring学习的第四篇文章,讲述了Spring框架中管理对象之间的关联关系。文章介绍了MessageService类和MessagePrinter类的实现,并解释了它们之间的关联关系。通过学习本文,读者可以了解Spring框架中对象之间的关联关系的概念和实现方式。 ... [详细]
  • Spring框架《一》简介
    Spring框架《一》1.Spring概述1.1简介1.2Spring模板二、IOC容器和Bean1.IOC和DI简介2.三种通过类型获取bean3.给bean的属性赋值3.1依赖 ... [详细]
author-avatar
漫步乡间2012
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有