热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

模拟Spring的简单实现

本文的主要内容就是学习Spring的开端,模拟一下Spring的实现,感兴趣的小伙伴可以参考一下

项目结构如下:

如何思考?面向抽象编程?
先来看看一个序列图

从以上看出了什么?初学的,能看得出是什么才怪,那不管它了。看看具体实现吧

首先要建立一个实体类:User,放在model包下

package com.wwj.model; 
 
/** 
 * 实体类 
 * @author wwj 
 * Spring 
 */ 
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; 
  } 
} 

下面就是叫你如何面向抽象编程,简单来说如何面向接口编程,下面定义一个接口

package com.wwj.dao; 
 
import com.wwj.model.User; 
 
/** 
 * 面向抽象编程 
 * @author wwj 
 * 优点:增加了灵活性 
 */ 
public interface UserDAO { 
  public void save(User user); 
} 

可以很清楚看到,这个接口声明了一个方法,save方法,里面有一个参数User对象,我们可以想到它是可以用来保存User对象到数据库里去的。

把具体实现交给实现类

package com.wwj.dao.impl; 
 
import com.wwj.dao.UserDAO; 
import com.wwj.model.User; 
 
/** 
 * 接口实现类 
 * @author wwj 
 * 
 */ 
public class UserDAOImpl implements UserDAO{ 
 
  @Override 
  public void save(User user) { 
    System.out.println("save user"); 
  } 
   
} 

这样做的好处是,如果你要更换数据库环境,你就能灵活定义不同的数据库代码了。
怎么调用以上的方法,为了使业务逻辑和数据库操作分离开,我们需要定义一个业务逻辑类

package com.wwj.service; 
 
import com.wwj.dao.UserDAO; 
import com.wwj.dao.impl.UserDAOImpl; 
import com.wwj.model.User; 
 
/** 
 * 服务类,实现业务逻辑 
 * @author wwj 
 * 
 */ 
public class UserService { 
  private UserDAO userDAO; 
   
  public UserDAO getUserDAO() { 
    return userDAO; 
  } 
 
  public void setUserDAO(UserDAO userDAO) { 
    this.userDAO = userDAO; 
  } 
 
  public void add(User user) { 
    this.userDAO.save(user); 
  } 
} 

我们可以看到,上面有一个东西,东西?UserDAO啊,看到它的作用了没有,看到才怪。这里设计到一个IOC也叫做DI的概念,中文意思叫做依赖注入,也叫控制反转,这在Spring是一个很重要的概念,要把它弄懂,才能很好的理解Spring的原理。

下面真正模拟Spring的实现,有点像工厂模式,利用Spring,我们可以把不同对象装配在一起使用。
先看一下配置文件beans.xml

 
   
   
     
   
 

一个工厂方法

package com.wwj.spring; 
 
public interface BeanFactory { 
  public Object getBean(String name); 
} 

一个解析xml文件的类,并实现BeanFactory

package com.wwj.spring; 
 
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.input.SAXBuilder; 
 
public class ClassPathXmlApplicationContext implements BeanFactory{ 
  //定义一个容器,用来存放对象 
  private Map beans = new HashMap(); 
   
   
  public ClassPathXmlApplicationContext() throws Exception{ 
    SAXBuilder sb = new SAXBuilder(); 
    Document doc = sb.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml")); 
    Element root = doc.getRootElement();  //获取根结点 
    List list = root.getChildren("bean");  //取名为bean的所有元素 
    for(int i = 0; i )element.getChildren("property")){ 
        String name = propertyElement.getAttributeValue("name");  //UserDAO 
        String bean = propertyElement.getAttributeValue("bean");  //u 
        Object beanObject = beans.get(bean);//UserDAOImpl instance 
         
        //拼凑方法名,实现setUserDAO方法 
        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);  //调用方法 
      } 
       
    } 
     
  } 
 
 
  @Override 
  public Object getBean(String name) { 
    return beans.get("id"); 
  } 
 
} 

来一个测试类

package com.wwj.service; 
 
import org.junit.Test; 
 
import com.wwj.model.User; 
import com.wwj.spring.BeanFactory; 
import com.wwj.spring.ClassPathXmlApplicationContext; 
 
/** 
 * 单元测试类 
 * @author wwj 
 * 
 */ 
public class UserServiceTest { 
   
  @Test 
  public void testAdd() throws Exception{ 
    BeanFactory beanFactory = new ClassPathXmlApplicationContext(); 
     
    UserService service =(UserService)beanFactory.getBean("userService"); 
    User u = new User(); 
    service.add(u); 
  } 
   
} 

从测试类我们可以看出点端倪了,首先定义一个BeanFactory对象,通过这个对象调换用其getBean的方法,获取业务逻辑类对象,后面就可以通过调用这个服务类的add方法把user对象添加到数据库中去。当然这里没有实现插入数据库,只是简单的实现了测试。其实整个过程很明了的,Spring的核心配置文件,将对象控制起来了,当要使用的时候就将对象注入到服务类当中去,服务类就可以利用DAO层的对象,进行数据库相关的操作。

以上就是整理的网上关于spring配置内容,希望可以对大家有所帮助。


推荐阅读
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • r2dbc配置多数据源
    R2dbc配置多数据源问题根据官网配置r2dbc连接mysql多数据源所遇到的问题pom配置可以参考官网,不过我这样配置会报错我并没有这样配置将以下内容添加到pom.xml文件d ... [详细]
  • 处理docker容器时间和宿主机时间不一致问题的方法
    本文介绍了处理docker容器时间和宿主机时间不一致问题的方法,包括复制主机的localtime到容器、处理报错情况以及重启容器的步骤。通过这些方法,可以解决docker容器时间和宿主机时间不一致的问题。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • 本文介绍了Java的集合及其实现类,包括数据结构、抽象类和具体实现类的关系,详细介绍了List接口及其实现类ArrayList的基本操作和特点。文章通过提供相关参考文档和链接,帮助读者更好地理解和使用Java的集合类。 ... [详细]
  • 本文介绍了电流源并联合并的方法,以及谐振电路的原理。谐振电路具有很强的选频能力,通过将电感和电容连接在一起,电流和电压会产生震荡。谐振频率的大小取决于电感和电容的大小,而电路中的电阻会逐渐降低震荡的幅度。电阻和电容组成的电路中,当电容放完电后,电阻两端的电压为0,电流不再流过电容。然而,电感是一种特殊的器件,当有电流流过时,线圈会产生感应磁场,阻止电流的流动,从而使电流不会减小。 ... [详细]
  • 标题: ... [详细]
  • 单点登录原理及实现方案详解
    本文详细介绍了单点登录的原理及实现方案,其中包括共享Session的方式,以及基于Redis的Session共享方案。同时,还分享了作者在应用环境中所遇到的问题和经验,希望对读者有所帮助。 ... [详细]
  • 网络请求模块选择——axios框架的基本使用和封装
    本文介绍了选择网络请求模块axios的原因,以及axios框架的基本使用和封装方法。包括发送并发请求的演示,全局配置的设置,创建axios实例的方法,拦截器的使用,以及如何封装和请求响应劫持等内容。 ... [详细]
  • iOS超签签名服务器搭建及其优劣势
    本文介绍了搭建iOS超签签名服务器的原因和优势,包括不掉签、用户可以直接安装不需要信任、体验好等。同时也提到了超签的劣势,即一个证书只能安装100个,成本较高。文章还详细介绍了超签的实现原理,包括用户请求服务器安装mobileconfig文件、服务器调用苹果接口添加udid等步骤。最后,还提到了生成mobileconfig文件和导出AppleWorldwideDeveloperRelationsCertificationAuthority证书的方法。 ... [详细]
  • 本文介绍了在Mac上安装Xamarin并使用Windows上的VS开发iOS app的方法,包括所需的安装环境和软件,以及使用Xamarin.iOS进行开发的步骤。通过这种方法,即使没有Mac或者安装苹果系统,程序员们也能轻松开发iOS app。 ... [详细]
  • 本文讨论了如何使用Web.Config进行自定义配置节的配置转换。作者提到,他将msbuild设置为详细模式,但转换却忽略了带有替换转换的自定义部分的存在。 ... [详细]
  • 本文介绍了如何使用JSONObiect和Gson相关方法实现json数据与kotlin对象的相互转换。首先解释了JSON的概念和数据格式,然后详细介绍了相关API,包括JSONObject和Gson的使用方法。接着讲解了如何将json格式的字符串转换为kotlin对象或List,以及如何将kotlin对象转换为json字符串。最后提到了使用Map封装json对象的特殊情况。文章还对JSON和XML进行了比较,指出了JSON的优势和缺点。 ... [详细]
  • 本文介绍了Android中的assets目录和raw目录的共同点和区别,包括获取资源的方法、目录结构的限制以及列出资源的能力。同时,还解释了raw目录中资源文件生成的ID,并说明了这些目录的使用方法。 ... [详细]
author-avatar
lovely--蕙蕙_868
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有