zoukankan      html  css  js  c++  java
  • 自己动手模拟spring的IOC

    我们这里是模拟spring,主要模拟spring中的IOC功能,所以在此我们一样要在service层中定义dao的实例,当然不用new出来,我们就通过spring的IOC把这里的dao层注入进来。不要忘了对dao提供set。Get方法,因为IOC的底层其实就是利用反射机制实现的,他把dao注入进来,其实底层就是通过反射set进来的。

    首先我们把我们用的dao、service、entity定义出来:

    1.  
      package org.spring.demo.entity;
    2.  
       
    3.  
      public class Student {
    4.  
       
    5.  
      private int id;
    6.  
      private String name;
    7.  
      private String memo;
    8.  
      private String address;
    9.  
       
    10.  
      public Student(int id, String name, String memo, String address) {
    11.  
      super();
    12.  
      this.id = id;
    13.  
      this.name = name;
    14.  
      this.memo = memo;
    15.  
      this.address = address;
    16.  
      }
    17.  
      public int getId() {
    18.  
      return id;
    19.  
      }
    20.  
      public void setId(int id) {
    21.  
      this.id = id;
    22.  
      }
    23.  
      public String getName() {
    24.  
      return name;
    25.  
      }
    26.  
      public void setName(String name) {
    27.  
      this.name = name;
    28.  
      }
    29.  
      public String getMemo() {
    30.  
      return memo;
    31.  
      }
    32.  
      public void setMemo(String memo) {
    33.  
      this.memo = memo;
    34.  
      }
    35.  
      public String getAddress() {
    36.  
      return address;
    37.  
      }
    38.  
      public void setAddress(String address) {
    39.  
      this.address = address;
    40.  
      }
    41.  
       
    42.  
       
    43.  
      }

    因为spring提倡的就是面向接口编程,所以在我们写dao层和service层具体实现之前,我们先定义接口,让我们的具体实现实现接口。

    1.  
      package org.spring.demo.service;
    2.  
       
    3.  
      import org.spring.demo.entity.Student;
    4.  
       
    5.  
      public interface StudentService {
    6.  
       
    7.  
      public void add(Student student);
    8.  
      }
    1.  
      package org.spring.demo.service.impl;
    2.  
       
    3.  
      import org.spring.demo.dao.StudentDao;
    4.  
      import org.spring.demo.entity.Student;
    5.  
      import org.spring.demo.service.StudentService;
    6.  
       
    7.  
      public class StudentServiceImp implements StudentService {
    8.  
       
    9.  
      StudentDao studentDao=null;
    10.  
       
    11.  
      public StudentDao getStudentDao() {
    12.  
      return studentDao;
    13.  
      }
    14.  
      public void setStudentDao(StudentDao studentDao) {
    15.  
      this.studentDao = studentDao;
    16.  
      }
    17.  
       
    18.  
      @Override
    19.  
      public void add(Student student) {
    20.  
      studentDao.add(student);
    21.  
       
    22.  
      }
    23.  
       
    24.  
      }
    1.  
      package org.spring.demo.dao;
    2.  
       
    3.  
      import org.spring.demo.entity.Student;
    4.  
       
    5.  
      public interface StudentDao {
    6.  
       
    7.  
      public void add(Student student);
    8.  
      }
    1.  
      package org.spring.demo.dao.impl;
    2.  
       
    3.  
      import org.spring.demo.dao.StudentDao;
    4.  
      import org.spring.demo.entity.Student;
    5.  
       
    6.  
      public class StudentDaoImp implements StudentDao {
    7.  
       
    8.  
      @Override
    9.  
      public void add(Student student) {
    10.  
      System.out.println(student.getName()+" is saved");
    11.  
      }
    12.  
       
    13.  
       
    14.  
      }

    下一步我们就是定义我们自己的ClassPathXmlApplicationContext类了,通过他,在我们new出他的对象的时候,他来加载配置文件,然后把我们的dao操作注入到我们的service层,在spring中,ClassPathXmlApplicationContext类实现了BeanFactory接口,在此我们也定义一个BeanFactory接口,其实这个接口没什么具体的作用,我们就是为了来模拟spring。在定义这个接口和实现类之前,我们先来看一下我们所需的xml是怎么编写的,下面我们就具体来看一下beans.xml的配置:

    1.  
      <?xml version="1.0" encoding="UTF-8"?>
    2.  
      <beans>
    3.  
      <bean id="studentDao" class="org.spring.demo.dao.impl.StudentDaoImp" />
    4.  
      <bean id="studentService" class="org.spring.demo.service.impl.StudentServiceImp" >
    5.  
      <property name="studentDao" bean="studentDao"/>
    6.  
      </bean>
    7.  
      </beans>

    看到这,相信大家都能感觉到这个配置文件太简单了,没有spring中那么多繁琐的配置,当然啦,我们这是只是实现其中的一个功能,spring提供了很多那么强大的功能,配置当然繁琐一些了。相信上边的代码不用我解释大家也能看懂了吧。

           好了,配置文件我们看完了,下一步我们一起来看一下我们的spring容器——ClassPathXmlApplicationContext具体是怎么实现的,我们首先还是来看一下他的接口定义:

    1.  
      package org.spring.demo.util;
    2.  
       
    3.  
      public interface BeanFactory {
    4.  
       
    5.  
      public Object getBean(String id);
    6.  
      }
    1.  
      package org.spring.demo.util;
    2.  
       
    3.  
      import java.lang.reflect.Method;
    4.  
      import java.util.HashMap;
    5.  
      import java.util.List;
    6.  
      import java.util.Map;
    7.  
       
    8.  
      import org.jdom.Document;
    9.  
      import org.jdom.Element;
    10.  
      import org.jdom.input.SAXBuilder;
    11.  
       
    12.  
      public class ClassPathXmlApplicationContext implements BeanFactory{
    13.  
       
    14.  
      private Map<String, Object> beans = new HashMap<String, Object>();
    15.  
       
    16.  
      public ClassPathXmlApplicationContext() throws Exception, Exception {
    17.  
      SAXBuilder sb = new SAXBuilder();
    18.  
      Document doc = sb.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml")); // 构造文档对象
    19.  
      Element root = doc.getRootElement(); // 获取根元素HD
    20.  
      List list = root.getChildren("bean");// 取名字为disk的所有元素
    21.  
      for (int i = 0; i < list.size(); i++) {
    22.  
      Element element = (Element) list.get(i);
    23.  
      String id = element.getAttributeValue("id");
    24.  
      String clazz = element.getAttributeValue("class");
    25.  
      Object o = Class.forName(clazz).newInstance();
    26.  
      System.out.println(id);
    27.  
      System.out.println(clazz);
    28.  
      beans.put(id, o);
    29.  
      for (Element propertyElement : (List<Element>) element.getChildren("property")) {
    30.  
      String name = propertyElement.getAttributeValue("name"); // userDAO
    31.  
      String bean = propertyElement.getAttributeValue("bean"); // u
    32.  
      Object beanObject = beans.get(bean);// UserDAOImpl instance
    33.  
      String methodName = "set" + name.substring(0, 1).toUpperCase()+ name.substring(1);
    34.  
      System.out.println("method name = " + methodName);
    35.  
      Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]);
    36.  
      m.invoke(o, beanObject);
    37.  
      }
    38.  
      }
    39.  
      }
    40.  
       
    41.  
      @Override
    42.  
      public Object getBean(String id) {
    43.  
      return beans.get(id);
    44.  
      }
    45.  
       
    46.  
      }

    首先我们定义了一个容器Map<String, Object> beans,这个容器的作用就是用来装我们从配置文件里解析来的一个个bean,为什么要用map类型,我想大家也差不多能猜到吧,我们配置文件中每一个bean都有一个id来作为自己的唯一身份。我们把这个id存到map的key里面,然后value就装我们的具体bean对象。说完这个容器之后,下面我们在来看一下ClassPathXmlApplicationContext的构造方法,这个构造方法是我们spring管理容器的核心,这个构造方法的前半部分是利用的jdom解析方式,把xml里面的bean一个个的解析出来,然后把解析出来的bean在放到我们bean容器里。如果这段代码看不懂的话,那你只好在去看看jdom解析xml了。好了,我们下面在来看一下这个构造的方法,后半部分主要是在对配置文件进行解析出bean的同时去查看一下这个bean中有没有需要注射bean的,如果有的话,他就去通过这些里面的property属性获取他要注射的bean名字,然后构造出set方法,然后通过反射,调用注入bean的set方法,这样我们所需要的bean就被注入进来了。如果这段代码你看不懂的话,那你只能去看一下有关反射的知识了。最后我们就来看一下实现接口的getBean放了,其实这个方法很简单,就是根据提供的bean的id,从bean容器内把对应的bean取出来。

    好了,我们所需的东西都定义好了,我们自己模仿的spring把我们所需要的dao层给我们注入进来。

    1.  
      package org.spring.demo;
    2.  
       
    3.  
      import org.spring.demo.entity.Student;
    4.  
      import org.spring.demo.service.StudentService;
    5.  
      import org.spring.demo.util.ClassPathXmlApplicationContext;
    6.  
       
    7.  
      public class SoringIOCTest {
    8.  
      public static void main(String[] args) throws Exception {
    9.  
      ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
    10.  
      StudentService service = (StudentService) context.getBean("studentService");
    11.  
      Student student = new Student(1,"刘一",null,null);
    12.  
      service.add(student);
    13.  
      }
    14.  
      }

    运行代码,控制台输出:
    studentDao
    org.spring.demo.dao.impl.StudentDaoImp
    studentService
    org.spring.demo.service.impl.StudentServiceImp
    method name = setStudentDao
    刘一 is saved

    好,成功注入进来,到此,我们模仿的spring就到此结束了.

    转自: https://blog.csdn.net/u011229848/article/details/52845821

  • 相关阅读:
    e621. Activating a Keystroke When Any Child Component Has Focus
    e587. Filling Basic Shapes
    e591. Drawing Simple Text
    e595. Drawing an Image
    e586. Drawing Simple Shapes
    e636. Listening to All Key Events Before Delivery to Focused Component
    在 PL/SQL 块的哪部分可以对初始变量赋予新值? (选择1项)
    Oracle数据库中,在SQL语句中连接字符串的方法是哪个?(选择1项)
    你判断下面语句,有什么作用?(单选)
    Oracle数据库表空间与数据文件的关系描述正确的是( )
  • 原文地址:https://www.cnblogs.com/dauber/p/9304343.html
Copyright © 2011-2022 走看看