实现SpringMVC底层机制(二)

04-27 811阅读

文章目录

    • 1. 动态获取spring配置文件
        • 1.修改SunWebApplicationContext.java
        • 2.修改SunDispatcherServlet.java
        • 2.自定义Service注解
            • 1.需求分析
            • 2.编写Monster.java
            • 3.自定义Service注解
            • 4.编写Service接口MonsterService.java
            • 5.编写Service实现类MonsterServiceImpl.java
            • 6.修改SunWebApplicationContext.java的executeInstance方法,增加对Service注解的扫描
            • 7.debug测试
            • 3.完成自定义Autowired注解
                • 1.自定义Autowired注解
                • 2.在SunWebApplicationContext.java中添加方法executeAutoWired完成属性的自动装配
                • 3.修改MonsterController.java来使用Autowired注解
                • 4.单元测试
                • 4.当前阶段完成的任务
                    • 自定义两个注解
                    • 目前对SpringMVC容器的简单理解

                      1. 动态获取spring配置文件

                      1.修改SunWebApplicationContext.java

                      实现SpringMVC底层机制(二)

                      2.修改SunDispatcherServlet.java

                      实现SpringMVC底层机制(二)

                      2.自定义Service注解

                      1.需求分析

                      实现SpringMVC底层机制(二)

                      2.编写Monster.java
                      package com.Sun.entity;
                      /**
                       * @author 孙显圣
                       * @version 1.0
                       */
                      public class Monster {
                          private Integer id;
                          private String name;
                          private String skill;
                          private Integer age;
                          public Monster(Integer id, String name, String skill, Integer age) {
                              this.id = id;
                              this.name = name;
                              this.skill = skill;
                              this.age = age;
                          }
                          public Integer getId() {
                              return id;
                          }
                          public void setId(Integer id) {
                              this.id = id;
                          }
                          public String getName() {
                              return name;
                          }
                          public void setName(String name) {
                              this.name = name;
                          }
                          public String getSkill() {
                              return skill;
                          }
                          public void setSkill(String skill) {
                              this.skill = skill;
                          }
                          public Integer getAge() {
                              return age;
                          }
                          public void setAge(Integer age) {
                              this.age = age;
                          }
                          @Override
                          public String toString() {
                              return "Monster{" +
                                      "id=" + id +
                                      ", name='" + name + '\'' +
                                      ", skill='" + skill + '\'' +
                                      ", age=" + age +
                                      '}';
                          }
                      }
                      
                      3.自定义Service注解
                      package com.Sun.sunspringmvc.annotation;
                      import java.lang.annotation.*;
                      /**
                       * 自定义注解,用于标识一个service
                       *
                       * @author 孙显圣
                       * @version 1.0
                       */
                      @Target(ElementType.TYPE) //作用于目标是类
                      @Retention(RetentionPolicy.RUNTIME) //作用范围
                      @Documented
                      public @interface Service {
                          String value() default "";
                      }
                      
                      4.编写Service接口MonsterService.java
                      package com.Sun.sunspringmvc.annotation;
                      import java.lang.annotation.*;
                      /**
                       * 自定义注解,用于标识一个service
                       *
                       * @author 孙显圣
                       * @version 1.0
                       */
                      @Target(ElementType.TYPE) //作用于目标是类
                      @Retention(RetentionPolicy.RUNTIME) //作用范围
                      @Documented
                      public @interface Service {
                      }
                      
                      5.编写Service实现类MonsterServiceImpl.java
                      package com.Sun.service.Impl;
                      import com.Sun.entity.Monster;
                      import com.Sun.service.MonsterService;
                      import com.Sun.sunspringmvc.annotation.Service;
                      import java.util.ArrayList;
                      import java.util.List;
                      /**
                       * @author 孙显圣
                       * @version 1.0
                       */
                      @Service
                      public class MonsterServiceImpl implements MonsterService {
                          public List listMonsters() {
                              ArrayList monsters = new ArrayList();
                              monsters.add(new Monster(1, "牛魔王", "芭蕉扇", 500));
                              monsters.add(new Monster(2, "蜘蛛精", "吐口水", 200));
                              return monsters;
                          }
                      }
                      
                      6.修改SunWebApplicationContext.java的executeInstance方法,增加对Service注解的扫描
                          //编写方法,将符合要求的类反射创建对象,并封装到单例池中
                          public void executeInstance() {
                              //遍历所有全类名
                              for (String classPath : classFullPathList) {
                                  try {
                                      //反射
                                      Class aClass = Class.forName(classPath);
                                      //判断是否有Controller注解
                                      if (aClass.isAnnotationPresent(Controller.class)) {
                                          //有注解,当他是单例的,反射创建bean对象,放到单例池中,默认首字母小写
                                          //获取类名首字母小写
                                          String name = aClass.getSimpleName().substring(0, 1).toLowerCase() + aClass.getSimpleName().substring(1);
                                          //放到单例池中
                                          singleObjects.put(name, aClass.newInstance());
                                      } else if (aClass.isAnnotationPresent(Service.class)) {
                                          //获取注解对象
                                          Service annotation = aClass.getAnnotation(Service.class);
                                          //获取注解的value
                                          String value = annotation.value();
                                          //为了使注入的都是同一个对象,所以在这里使用反射创建实例
                                          Object bean = aClass.newInstance();
                                          //如果注解的value是空的,则使用默认机制注入到单例池中
                                          if ("".equals(value)) {
                                              //1.使用类名首字母小写来注入
                                              String simpleName = aClass.getSimpleName();
                                              String beanName = simpleName.substring(0,1).toLowerCase() + simpleName.substring(1);
                                              singleObjects.put(beanName, bean);
                                              //2.使用接口名首字母小写来注入
                                              Class[] interfaces = aClass.getInterfaces();
                                              //遍历所有接口类型,进行注入
                                              for (Class anInterface : interfaces) {
                                                  //获取接口的名称
                                                  String interfaceSimpleName = anInterface.getSimpleName();
                                                  //获取首字母小写
                                                  String beanName2 = interfaceSimpleName.substring(0,1).toLowerCase() + interfaceSimpleName.substring(1);
                                                  //进行注入
                                                  singleObjects.put(beanName2, bean);
                                              }
                                          } else {
                                              //如果value不是空的,则按照value的值进行注入
                                              singleObjects.put(value, bean);
                                          }
                                      }
                                  } catch (ClassNotFoundException e) {
                                      throw new RuntimeException(e);
                                  } catch (InstantiationException e) {
                                      throw new RuntimeException(e);
                                  } catch (IllegalAccessException e) {
                                      throw new RuntimeException(e);
                                  }
                              }
                          }
                      
                      7.debug测试

                      实现SpringMVC底层机制(二)

                      3.完成自定义Autowired注解

                      1.自定义Autowired注解
                      package com.Sun.sunspringmvc.annotation;
                      import java.lang.annotation.*;
                      /**
                       * @author 孙显圣
                       * @version 1.0
                       */
                      @Target(ElementType.FIELD) //作用目标是字段
                      @Retention(RetentionPolicy.RUNTIME) //作用范围
                      @Documented
                      public @interface AutoWired {
                          String value() default "";
                      }
                      
                      2.在SunWebApplicationContext.java中添加方法executeAutoWired完成属性的自动装配

                      实现SpringMVC底层机制(二)

                          //编写方法,完成属性的自动装配
                          public void executeAutoWired() throws IllegalAccessException {
                              //首先判断容器是否为空
                              if (singleObjects.isEmpty()) {
                                  return;
                              }
                              //遍历容器中的所有bean对象
                              for (Object beanObject : singleObjects.values()) {
                                  //得到Class对象
                                  Class aClass = beanObject.getClass();
                                  //得到所有字段
                                  Field[] declaredFields = aClass.getDeclaredFields();
                                  for (Field declaredField : declaredFields) {
                                      //判断这些字段是否有自动装配的注解
                                      if (declaredField.isAnnotationPresent(AutoWired.class)) {
                                          //得到这个注解的value
                                          AutoWired annotation = declaredField.getAnnotation(AutoWired.class);
                                          String value = annotation.value();
                                          Object findBeanObject = null; //用来存储从容器中查找到的值
                                          //先判断这个注解的value有没有值
                                          if ("".equals(value)) {
                                              //如果注解没有值则按照默认的方式处理,即按照类型的首字母小写来查找
                                              String simpleName = declaredField.getType().getSimpleName();
                                              String beanName = simpleName.substring(0, 1).toLowerCase() + simpleName.substring(1);
                                              //从容器中查找
                                              findBeanObject = singleObjects.get(beanName);
                                          } else {
                                              //这个注解的value不是空的,则按照他的这个value在容器中查找
                                              findBeanObject = singleObjects.get(value);
                                          }
                                          if (findBeanObject == null) {
                                              throw new RuntimeException("容器中不存在你要装配的bean");
                                          } else {
                                              //进行依赖注入,需要指定给哪个对象的字段赋值
                                              //反射爆破
                                              declaredField.setAccessible(true);
                                              declaredField.set(beanObject, findBeanObject);
                                          }
                                      }
                                  }
                              }
                          }
                      
                      3.修改MonsterController.java来使用Autowired注解

                      实现SpringMVC底层机制(二)

                      4.单元测试

                      实现SpringMVC底层机制(二)

                      实现SpringMVC底层机制(二)

                      4.当前阶段完成的任务

                      自定义两个注解
                      • 自定义Service注解:在原有的扫描所有文件全类名的基础上增加逻辑,判断是否具有Service注解,并根据value值或者默认方案将其注入到bean中
                      • 自定义Autowired注解
                        • 遍历所有单例池对象,获取对应的Class对象
                        • 获取每个对象的所有字段
                        • 对每个字段判断是否有Autowired注解,如果有则按照类型首字母小写或者value值来进行依赖注入
                          目前对SpringMVC容器的简单理解
                          • tomcat启动,加载中央控制器
                          • 获取spring配置文件路径,使用这个路径创建一个spring容器
                          • 调用spring容器的init方法,初始化spring容器
                            • 读取配置文件,得到要扫描的包,从而得到包的工作路径
                            • 根据工作路径来得到包内所哟class文件的全路径
                            • 遍历所有class文件的全路径,得到Class对象
                            • 使用反射扫描指定注解,反射创建bean对象,放到单例池中
                            • Autowired依赖注入
                              • 扫描单例池,得到所有对象,从而得到Class对象
                              • 使用反射得到所有字段信息,判断是否有Autowied注解,如果有则根据一定规则从单例池中查找bean对象进行依赖注入
                              • 初始化映射对象列表
                                • 扫描单例池,得到Class对象
                                • 通过反射判断是否有RequestMapping注解,如果有则使用反射获取url和Method对象,再加上当前的对象,封装到映射对象中
                                • 将这个映射对象添加到映射对象列表
                                • 请求分发
                                  • 浏览器向中央控制器发送请求
                                  • 中央控制器根据请求的uri和映射对象列表的url进行比对
                                  • 如果匹配则反射调用Controller的方法
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]