知音专栏

程序员的出路

写程序时该追求什么,什么是次要的?

如何准备Java初级和高级的技术面试

算法的力量,李开复聊算法的重要性

我们平日开发时所用的SSM框架,可是你真的了解它吗?技术革新,换代应接不暇,只有理解了源码才能保证在技术快速更迭的时代中真正站稳脚跟。

本系列文章抽丝剥茧,源码分析百度有很多,在这里只列举几个我收录的优秀的博客推荐给大家,本文不过多的分析源码,更注重将代码理解后的实现。

话不多说,开启正题。(由于本人是小白,理解的不深所以写出来的东西比较浅显易懂。如果有错误还望各位大佬指出来,帮助我提高)

项目介绍:此项目是在手写SSM框架的基础上开发了一个简单的登录功能。

首先是spring框架的实现,spring的依赖注入特性是集成其他所有框架的基础。在spring2.5版本之前,只支持配置文件注入。在2.5之后加入了@Autowired注解,实现了注解注入。我们的这个spring框架当然是都支持啦。首先是xml版本注入。目前支持的是构造器注入和set属性注入。

实现思路:

用dom4j解析xml文件。获取各个节点的属性和内容。

用枚举定义IOC的bean的规则,用BeanFacory的getBean方法读取配置信息,如果xml读取到的属性和IOCRULES的枚举内容匹配的话,用BeanDefinitionMap对象保存,然后用反射实例化一个对象。

读取在xml文件中读取到的扫包路径,扫描此路径下的有注解的类按照自下而上的顺序存储在componentList中。

将componentList对象按照顺序实例化出对象。

一些高大上的名词,其实就是一些对象或者数据结构。比如我们常说的spring容器其实就指的是一个map对象集合,在spring源码其实就是DefaultListableBeanFactory类中如下对象

private final Map<String, BeanDefinition> beanDefinitionMap= new ConcurrentHashMap<String, BeanDefinition>(256);

将这些对象实例化之后就是我们说的注入。再比如springmvc中的handlerMapping,其实就是map集合,key是方法名,value是@RequestMapping的路径。再比如...还有很多,在实战之前我先提出几个我自己想到的问题,希望大家看的时候带着问题提来看:

spring有xml配置,也有注解配置,那么先实例化的是哪种版本呢?

构造器注入,属性注入如何实现的?

在指定包的路径下有那么多要注入的bean,service层调用dao,所以dao层一定要在service之前注入,然后在service层属性注入的时候才能将dao层注入,那么如何保证实例化的顺序呢?这也是难点。

我们使用的时候只需要用@Autowired标记接口,即可使用。但是我们知道接口并不能实例化对象,那么spring是如何做到的呢?而且有的接口有实现类,在mybatis中连实现类都没有,如何实现的呢?

效果图


下面开始实战:

  1. 项目必须用jdk1.8,不然会报错.里面一些方法只有1.8才有。

  2. 用到了lombok这个jar包,主要是简化了代码量,一个注解就可以省略getset方法。

  3. 解析xml用的dom4j,在小型xml文件的解析和操作中dom4j是最佳选择

  4. 在最后的demo中,RegisterServiceImpl,UserServiceImpl,RegisterService,UserService等文件没有真正的使用。只是考虑多层注入的时候,为了测试注入的顺序是否是对的。在dao层真正用的是UserMapper这个接口。

先介绍一下工具类吧。省的代码中出现的时候大家看不懂

package spring.Utils;/*** Created by Xiao Liang on 2018/6/27.* 注解工具类:判断注解是否为空*/public class  AnnotationUtils {   public  static <T>  boolean isEmpty(T t){       return  t == null ? true : false;   }}
package spring.Utils;/*** @ClassName ConvertUtis* @Description 根据传入的属性和类名,将属性名强转为类名的属性* @Data 2018/7/4* @Author xiao liang*/public class ConvertUtis {   public static Object  convert(String className,String parameter){       if (className.equals("String")){           return parameter;       }       else if (className.equals("Integer")){           return Integer.valueOf(parameter);       }       else if (className.equals("int")){           return Integer.valueOf(parameter);       }       else if (className.equals("Float")){           return Float.valueOf(parameter);       }       else if (className.equals("Double")){           return Integer.valueOf(parameter);       }       else if (className.equals("Long")){           return Long.valueOf(parameter);       }       else if (className.equals("Short")){           return Short.valueOf(parameter);       }       else if (className.equals("Byte")){           return Byte.valueOf(parameter);       }       else if (className.equals("Boolean")){           return Boolean.valueOf(parameter);       }       return null;   }}
package spring.Utils;/*** @ClassName GetMethodName* @Description 根据属性名拼接set方法* @Data 2018/7/4* @Author xiao liang*/public class GetMethodName {   public   static  String getSetMethodNameByField(String propertyName) {       String methodName = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);       return methodName;   }}
package spring.Utils;/*** @ClassName isBasicType* @Description 判断是不是基本数据类型* @Data 2018/7/4* @Author xiao liang*/public class isBasicTypeUtils {   public static boolean  isBasicType(String typeName){       if (typeName.equals("String")){           return true;       }       else if(typeName.equals("Integer")){           return true;       }       else if(typeName.equals("int")){           return true;       }       else if(typeName.equals("Long")){           return true;       }       else if(typeName.equals("Short")){           return true;       }       else if(typeName.equals("Float")){           return true;       }       else if(typeName.equals("Double")){           return true;       }       else if(typeName.equals("Byte")){           return true;       }       return false;   }}
package spring.Utils;import java.util.HashSet;import java.util.List;import java.util.Set;/***  @Author xiao liang*  @Desprition 在链表中添加数据,添加时保证只有一个相同的实例*/public class ListAddUtils {   public static <T> void add(List<T> list ,T t) {       Set<T> set1 = new HashSet<>(list);       if (set1.add(t)){           list.add(t);       }   }}
package spring.Utils;/***  @Author xiao liang*  判断字符串是否为空*/public class StringUtils {   public static boolean isEmpty(String string) {       if ((string == null) || "".equals(string)) {           return true;       }       return false;   }}

还有一个常量类。

package spring.constants;import spring.xml.FileSystemXmlApplicationContext;/*** Created by Xiao Liang on 2018/6/27.* @Description :保存的是各个配置文件的路径*/public interface Constants {   String PATH = FileSystemXmlApplicationContext.class.getResource("/").getPath();   String contextConfigLocation = "application.xml";   String springmvcConfigLocation = "spring-mvc.xml";   String mybatisConfigLocation = "MyUserMapper.xml";}

还有三个xml文件:

application.xml

<?xml version="1.0" encoding="UTF-8"?><beans>   <bean id="hostess" class="spring.Person">       <property name ="userName" value = "admin"></property>       <property name ="passWord" value = "admin"></property>   </bean>   <bean class="spring.mybatis.JDBCUtils" id="dataSource">       <property name="user" value="root"></property>       <property name="password" value="qinliang"></property>       <property name="driver" value="com.mysql.jdbc.Driver"></property>       <property name="url" value="jdbc:mysql://localhost:3306/test"></property>   </bean>   <component-scan base-package="spring.demo" >   </component-scan></beans>

springmvc.xml

<?xml version="1.0" encoding="UTF-8"?><beans>   <bean id="viewResolver" class="spring.springmvc.ViewResolver">       <property name="prefix" value="/WEB-INF/views/"></property>       <property name="suffix" value=".jsp"></property>   </bean></beans>

MyUserMapper.xml

<?xml version="1.0" encoding="UTF-8"?><mapper namespace="spring.demo.repository.UserMapper">   <select id="queryUser" resultType="spring.dataObject.User">       select * from login_user where username = #{username} AND password = #{password}   </select></mapper>

这是一个maven项目,pom.xml文件内容如下

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">   <modelVersion>4.0.0</modelVersion>   <groupId>com.myspring</groupId>   <artifactId>start</artifactId>   <version>1.0-SNAPSHOT</version>   <packaging>war</packaging>   <name>start Maven Webapp</name>   <!-- FIXME change it to the project's website -->   <url>http://www.example.com</url>   <properties>       <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>       <maven.compiler.source>1.8</maven.compiler.source>       <maven.compiler.target>1.8</maven.compiler.target>   </properties>   <dependencies>       <dependency>           <groupId>junit</groupId>           <artifactId>junit</artifactId>           <version>4.11</version>           <scope>test</scope>       </dependency>       <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->       <dependency>           <groupId>org.projectlombok</groupId>           <artifactId>lombok</artifactId>           <version>1.18.0</version>           <scope>provided</scope>       </dependency>       <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->       <dependency>           <groupId>org.slf4j</groupId>           <artifactId>slf4j-api</artifactId>           <version>1.7.25</version>       </dependency>       <dependency>           <groupId>org.slf4j</groupId>           <artifactId>slf4j-simple</artifactId>           <version>1.7.25</version>       </dependency>       <dependency>           <groupId>javax.servlet</groupId>           <artifactId>servlet-api</artifactId>           <version>2.5</version>       </dependency>       <dependency>           <groupId>javax.servlet.jsp</groupId>           <artifactId>jsp-api</artifactId>           <version>2.1.3-b06</version>       </dependency>       <dependency>           <groupId>dom4j</groupId>           <artifactId>dom4j</artifactId>           <version>1.6.1</version>       </dependency>       <!-- https://mvnrepository.com/artifact/jstl/jstl -->       <dependency>           <groupId>jstl</groupId>           <artifactId>jstl</artifactId>           <version>1.2</version>       </dependency>       <!--数据库连接池和数据库连接-->       <dependency>           <groupId>mysql</groupId>           <artifactId>mysql-connector-java</artifactId>           <version>5.1.8</version>       </dependency>   </dependencies>   <build>       <finalName>start</finalName>       <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->           <plugins>               <plugin>                   <artifactId>maven-clean-plugin</artifactId>                   <version>3.0.0</version>               </plugin>               <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->               <plugin>                   <artifactId>maven-resources-plugin</artifactId>                   <version>3.0.2</version>               </plugin>               <plugin>                   <artifactId>maven-compiler-plugin</artifactId>                   <version>3.7.0</version>               </plugin>               <plugin>                   <artifactId>maven-surefire-plugin</artifactId>                   <version>2.20.1</version>               </plugin>               <plugin>                   <artifactId>maven-war-plugin</artifactId>                   <version>3.2.0</version>               </plugin>               <plugin>                   <artifactId>maven-install-plugin</artifactId>                   <version>2.5.2</version>               </plugin>               <plugin>                   <artifactId>maven-deploy-plugin</artifactId>                   <version>2.8.2</version>               </plugin>           </plugins>       </pluginManagement>   </build></project>

下面是项目的业务逻辑代码,可以过一下,就是最简单的三层架构。业务逻辑代码中中有一些为了测试用,并没有实际的意义

package spring.demo.controller;import spring.annotation.MyAutowired;import spring.annotation.MyController;import spring.annotation.MyModelAttribute;import spring.annotation.MyRequestMapping;import spring.dataObject.User;import spring.demo.service.UserService;import spring.springmvc.MyModelAndView;import spring.springmvc.MyModelMap;import spring.xmlRules.RequestMethod;/*** Created by Xiao Liang on 2018/6/27.*/@MyControllerpublic class LoginController {   @MyAutowired   private UserService userService;   //测试用的@MyRequstParam(value = "userName") String userName,  @MyRequstParam(value = "passWord") Integer passWord   //返回值只支持MyModelAndView,数据模型和视图模型相结合   @MyRequestMapping(value = "/hello", method = RequestMethod.POST)   public MyModelAndView login(@MyModelAttribute("User") User user) {       MyModelAndView myModelAndView = new MyModelAndView("success");       MyModelMap myModel = new MyModelMap();       User user1 = userService.queryUser("admin", "admin");       myModel.addAttribute("test", user1.getUserName());       myModelAndView.setModelMap(myModel);       return myModelAndView;   }   @MyRequestMapping("/hello22")   public String test() {       return "success";   }}
package spring.demo.controller;import spring.annotation.MyAutowired;import spring.annotation.MyController;import spring.annotation.MyRequestMapping;import spring.demo.service.RegisterService;import spring.demo.service.UserService;/*** Created by Xiao Liang on 2018/6/27.*/@MyControllerpublic class RegisterController {   @MyAutowired   private UserService userService;   @MyAutowired   private RegisterService registerService;   @MyRequestMapping("/register")   public void regeister(){       userService.queryUser("","");       registerService.register();   }}
package spring.demo.service;import spring.dataObject.User;/*** Created by Xiao Liang on 2018/6/27.*/public interface UserService {    User queryUser(String userName, String passWord);}package spring.demo.service;/*** Created by Xiao Liang on 2018/6/27.*/public interface RegisterService {   void register();}
package spring.demo.service.impl;import spring.annotation.MyAutowired;import spring.annotation.MyService;import spring.dataObject.User;import spring.demo.repository.RegisterDao;import spring.demo.repository.UserDao;import spring.demo.repository.UserMapper;import spring.demo.service.UserService;/*** Created by Xiao Liang on 2018/6/27.*/@MyServicepublic class UserServiceImpl implements UserService {   @MyAutowired   private UserDao userDao;   @MyAutowired   private RegisterDao registerDao;   @MyAutowired   private UserMapper userMapper;   @Override   public User queryUser(String userName, String passWord) {       return userMapper.queryUser(userName,passWord);   }}
package spring.demo.service.impl;import spring.annotation.MyAutowired;import spring.annotation.MyService;import spring.demo.repository.RegisterDao;import spring.demo.service.RegisterService;/*** Created by Xiao Liang on 2018/6/27.*/@MyServicepublic class RegisterServiceImpl implements RegisterService{   @MyAutowired   private RegisterDao registerDao;   @Override   public void register() {       registerDao.register();   }}
package spring.demo.repository;/*** Created by Xiao Liang on 2018/6/27.*/public interface UserDao {     void test();}
package spring.demo.repository;/*** Created by Xiao Liang on 2018/6/27.*/public interface RegisterDao {    void register();}
package spring.demo.repository.impl;import spring.annotation.MyRepository;import spring.demo.repository.UserDao;/*** Created by Xiao Liang on 2018/6/27.*/@MyRepositorypublic class UserDaoImpl implements UserDao {   @Override   public void test() {       System.out.println("我是UserDao");   }}
package spring.demo.repository.impl;import spring.annotation.MyRepository;import spring.demo.repository.RegisterDao;/*** Created by Xiao Liang on 2018/6/27.*/@MyRepositorypublic class RegisterDaoImpl implements RegisterDao{   @Override   public void register() {       System.out.println("我是RegisterDao");   }}
package spring.demo.repository;import spring.dataObject.User;/*** @ClassName UserMapper* @Description* @Data 2018/7/7* @Author xiao liang*/public interface UserMapper {   User queryUser(String userName,String passWord);}

我将此项目上传到了github,需要的童鞋可以点击下方阅读原文自行下载。

©著作权归作者所有:来自51CTO博客作者mob604756f6460e的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 手写spring+springmvc+mybatis框架篇【springmvc】
  2. 就是要让你彻底学会 @Bean 注解
  3. 孙卫琴的《精通JPA与Hibernate》的读书笔记:用@ManyToMany注解映
  4. 孙卫琴的《精通JPA与Hibernate》的读书笔记:用@OneToOne注解映射
  5. Linux 运维需要掌握的 17 个实用技巧
  6. IOC 控制反转与 DI 依赖注入
  7. SpringMVC_Day01
  8. spring-boot+mybatis开发实战:如何在spring-boot中使用myabtis持
  9. Spring注解 @Resource和@Autowired比较

随机推荐

  1. 如何将jQuery输入掩码实现到@ Html.TextB
  2. 是否可以在两行中输出'submit'的值?
  3. 固定定位,父元素具有转换
  4. 49、html基础认识&常用标签(1)
  5. html5第十课时,简单的计算器
  6. [转]Html position(static、relative、abs
  7. 零基础HTML5游戏制作教程 第3章 图形的移
  8. MonoRail学习笔记十三:NVelocity的增强功
  9. [模仿]html5游戏_别踩白块
  10. 的良好实践是什么?它可以替换还是只用于