模拟spring原理的实现

  Spring 表示是一个开源框架,是为了解决企业应用程序开发复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。(以上来自百度百科)

下面就先来自己实现一个spring的小例子:

首先有一个实体类User位于model包下

public class User {

   private String username;

   private String password;

   
   public String getUsername() {

      return username;

   }

   public void setUsername(String username) {

      this.username = username;

   }

   public String getPassword() {

      return password;

   }

   public void setPassword(String password) {

      this.password = password;

   }  

} 

然后是一个UserDAO接口位于dao包下

public interface UserDAO {

   public void save(User u);

}

接着是实现了UserDAO接口的UserDAOImpl类位于dao包下的impl包中 

public class UserDAOImpl implements UserDAO{

   public void save(User u){

      System.out.println("a user saved!");

   }

}

还有一个UserService类来对User进行增删改查位于service包中

public class UserService {

   private UserDAO userDAO; 

   public UserDAO getUserDAO() {

      return userDAO;

   } 

   public void setUserDAO(UserDAO userDAO) {

      this.userDAO = userDAO;

   }
 
   public void add(User u){

      userDAO.save(u); 

   }

}

UserService对外公开的只是它的业务逻辑,而UserDAO负责和DB打交道,就可以写多个实现了UserDAO接口的类了如UserDAOImpl,这就是面向抽象编程(面向接口),它是程序有更多的灵活性。但是如果有很多个ServiceTeacherService,ScoreService等等,就可以用一个大的总的工厂来产生所有这些DAOUserDAO,XML文件来对这些进行配置,用JDOM来读取XML文件 

XML文件: 

<beans>

   <bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl" />

   <bean id="userService" class="com.bjsxt.service.UserService" >

      <property name="userDAO" bean="u"/>

   </bean>

</beans>

Property指的是set方法,在UserService中有个方法叫setUserDAO,当它初试化的时候应该把id="u"所对应的class对象传进来,这样就把userService中的UserDAOUserDAOImpl装配到一起了,这就叫注入。

现在来模拟Spring原理,spring中有一个类ClassPathXmlApplicationContext的作用是把读取的XML中的信息存入到一个容器,将来要用就直接从中拿,它实现了一个BeanFactory接口,以上完全是为了模拟spring,但是这些类和接口在spring中确实存在,而且名字相同。

ClassPathXmlApplicationContext的实现如下:

import java.lang.reflect.Method;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import org.jdom2.Document;

import org.jdom2.Element;

import org.jdom2.input.SAXBuilder;

public class ClassPathXmlApplicationContext implements BeanFactory {

   private Map<String, Object> beans = new HashMap<String, Object>();

   public Object getBean(String id) {

      return this.beans.get(id);

   }

   public ClassPathXmlApplicationContext() throws Exception{

      SAXBuilder sb = new SAXBuilder();

      Document doc = sb.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml")); // 构造文档对象

       Element root = doc.getRootElement(); // 获取根元素HD

      List<Element> list = root.getChildren("bean");// 取名字为disk的所有元素

       for (int i = 0; i < list.size(); i++) {

         Element element = (Element) list.get(i);

         String id = element.getAttributeValue("id");

         String clazz = element.getAttributeValue("class");

         Object o = Class.forName(clazz).newInstance();

         System.out.println(id+":"+clazz);

         beans.put(id, o);

         for(Element propertyElement:(List<Element>)element.getChildren("property")){

            String name = propertyElement.getAttributeValue("name");

            String bean = propertyElement.getAttributeValue("bean");

            Object beanObject = beans.get(bean);

            String methodName = "set" + name.substring(0,1).toUpperCase()+ name.substring(1);

            System.out.println("method name= "+methodName);
            
            Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]);

            m.invoke(o, beanObject);

         }

      }

   }

}

上面用到了反射机制

BeanFactory的实现如下:

publicinterface BeanFactory {

   public Object getBean(String id);

}

下面来用Junit进行测试,关于Junit的知识将作为一个专题在后面讲解。

import java.io.IOException;

import org.jdom2.JDOMException;

import org.junit.Test;

import com.bjsxt.dao.UserDAO;

import com.bjsxt.model.User;

import com.bjsxt.spring.BeanFactory;

import com.bjsxt.spring.ClassPathXmlApplicationContext;
 
publicclass UserServiceTest {
  
   @Test

   publicvoid testAdd() throws Exception{

      BeanFactory factory = new ClassPathXmlApplicationContext();

      UserService service = (UserService)factory.getBean("userService");

//    UserDAO userDAO = (UserDAO)factory.getBean("u");

//    service.setUserDAO(userDAO);

      User u = new User();

      service.add(u);

   }

}

分层模型:

Test通过add(User)方法来调用UserService对象,通过UserService来调用UserDAO,UserDAO可以调用User对象又可以把数据导入DB,通过UserDAO可以提供对数据库的屏蔽,只是提供UserService接口

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐