• 自己实现 SpringMVC 底层机制 系列之-实现任务阶段 5- 完成 Spring 容器对象的自动装配 -@Autowried


    😀前言
    自己实现 SpringMVC 底层机制 系列之-实现任务阶段 5- 完成 Spring 容器对象的自动装配 -@Autowried

    🏠个人主页尘觉主页
    在这里插入图片描述

    🧑个人简介:大家好,我是尘觉,希望我的文章可以帮助到大家,您的满意是我的动力😉😉

    在csdn获奖荣誉: 🏆csdn城市之星2名
    ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ 💓Java全栈群星计划top前5
    ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ ⁣⁣⁣⁣ 🤗 端午大礼包获得者

    💕欢迎大家:这里是CSDN,我总结知识的地方,欢迎来到我的博客,感谢大家的观看🥰
    如果文章有什么需要改进的地方还请大佬不吝赐教 先在次感谢啦😊

    😃实现任务阶段 5- 完成 Spring 容器对象的自动装配 -@Autowried

    说明: 完成 Spring 容器中对象的注入/自动装配

    😉分析示意图

    img

    - 浏览器输入 http://localhost:8080/monster/list, 返回列表信息

    img

    ● 代码实现, 说明,整个实现思路,就是参考 SpringMVC 规范

    代码实现

    创建自定义注解AutoWired
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface AutoWired {
        String value() default "";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    修改MonsterController
    public class MonsterController {
    
        //@AutoWired表示要完成属性的装配.
        @AutoWired
        private MonsterService monsterService;
    
        //编写方法,可以列出妖怪列表
        //springmvc 是支持原生的servlet api, 为了看到底层机制
        //这里我们设计两个参数
        @RequestMapping(value = "/monster/list")
        public void listMonster(HttpServletRequest request,
                                HttpServletResponse response) {
            //设置编码和返回类型
            response.setContentType("text/html;charset=utf-8");
    
            StringBuilder content = new StringBuilder("

    妖怪列表信息

    "
    ); //调用monsterService List<Monster> monsters = monsterService.listMonster(); content.append("");for(Monster monster : monsters){ content.append("");} content.append("
    " + monster.getId() + "" + monster.getName() + "" + monster.getSkill() + "" + monster.getAge() + "
    "
    ); //获取writer返回信息 try { PrintWriter printWriter = response.getWriter(); printWriter.write(content.toString()); } catch (IOException e) { e.printStackTrace(); } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    修改WyxWebApplicationContext
    public class WyxWebApplicationContext {
        //定义属性classFullPathList, 保存扫描包/子包的类的全路径
        private List<String> classFullPathList =
                new ArrayList<>();
        //定义属性ioc, 存放反射生成的Bean对象 /Controller/Service
        public ConcurrentHashMap<String, Object> ioc =
                new ConcurrentHashMap<>();
    
        //无参构造器
        public WyxWebApplicationContext() {
        }
    
        private String configLocation;//属性,表示spring容器配置文件
    
        public WyxWebApplicationContext(String configLocation) {
            this.configLocation = configLocation;
        }
    
        //编写方法,完成自己的spring容器的初始化
        public void init() {
            //这里是写的固定的spring容器配置文件.?=>做活
            //String basePackage = XMLParser.getBasePackage("wyxspringmvc.xml");
            String basePackage =
                    XMLParser.getBasePackage(configLocation.split(":")[1]);
            //这时basePackage => com.hspedu.controller,com.wyxdu.service
            String[] basePackages = basePackage.split(",");
            //遍历basePackages, 进行扫描
            if (basePackages.length > 0) {
                for (String pack : basePackages) {
                    scanPackage(pack);//扫描
                }
            }
            System.out.println("扫描后的= classFullPathList=" + classFullPathList);
            //将扫描到的类, 反射到ico容器
            executeInstance();
            System.out.println("扫描后的 ioc容器= " + ioc);
    
            //完成注入的bean对象,的属性的装配
            executeAutoWired();
            System.out.println("装配后 ioc容器= " + ioc);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    executeAutoWired();方法调用
        public void executeAutoWired() {
            //判断ioc有没有要装配的对象
            if (ioc.isEmpty()) {
                return; //你也可以抛出异常 throw new RuntimeException("ioc 容器没有bean对象")
            }
            //遍历ioc容器中的所有注入的bean对象, 然后获取到bean的所有字段/属性,判断是否需要
            //装配
            /**
             * entry =>  String 就是你注入对象时名称 Object就是bean对象
             */
            for (Map.Entry<String, Object> entry : ioc.entrySet()) {
    
                //String key = entry.getKey();
                Object bean = entry.getValue();
    
                //得到bean的所有字段/属性
                Field[] declaredFields = bean.getClass().getDeclaredFields();
                for (Field declaredField : declaredFields) {
                    //判断当前这个字段,是否有@AutoWired
                    if (declaredField.isAnnotationPresent(AutoWired.class)) {//有@AutoWired
    
                        //的当前这个字段的@AutoWired
                        AutoWired autoWiredAnnotation = declaredField.getAnnotation(AutoWired.class);
                        String beanName = autoWiredAnnotation.value();
                        if ("".equals(beanName)) {//如果没有设置value,按照默认规则
                            //即得到字段类型的名称的首字母小写,作为名字来进行装配
                            Class<?> type = declaredField.getType();
                            beanName = type.getSimpleName().substring(0, 1).toLowerCase() +
                                    type.getSimpleName().substring(1);
                        }
                        //如果设置value, 直接按照beanName来进行装配
                        //从ioc容器中获取到bean
                        if (null == ioc.get(beanName)) {//说明你指定的名字对应的bean不在ioc容器
                            throw new RuntimeException("ioc容器中, 不存在你要装配的bean");
                        }
                        //防止属性是private, 我们需要暴力破解
                        declaredField.setAccessible(true);
                        //可以装配属性
                        try {
                            declaredField.set(bean, ioc.get(beanName));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
    
                    }
                }
    
            }
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    启动 Tomcat, 完成测试

    浏览器输入 http://localhost:8080/monster/list

    img

    😄总结

    本文完成了实现任务阶段 5- 完成 Spring 容器对象的自动装配 -@Autowried 下面就是
    实现任务阶段 6- 完成控制器方法获取参数-@RequestParam
                          
                          
    😉自己实现 SpringMVC 底层机制 核心分发 控制器+ Controller 和 Service 注入容器 + 对象自动装配 + 控制器 方法获取参数 + 视图解析 + 返回 JSON 格式数系列

    第一篇->自己实现 SpringMVC 底层机制 系列之搭建 SpringMVC 底层机制开发环境和开发 WyxDispatcherServlet_springmvc分发器

    第二篇->自己实现 SpringMVC 底层机制 系列之–实现任务阶段 2- 完成客户端浏览器可以请求控制层

    第三篇->自己实现 SpringMVC 底层机制 系列之–实现任务阶段 3- 从 web.xml动态获取 wyxspringmvc.xml

    第四篇-> 自己实现 SpringMVC 底层机制 系列之-实现任务阶段 4- 完成自定义@Service 注解功能

    第五篇-> 自己实现 SpringMVC 底层机制 系列之-实现任务阶段 5- 完成 Spring 容器对象的自动装配 -@Autowried

    第六篇->自己实现 SpringMVC 底层机制 系列之-实现任务阶段 6-完成控制器方法获取参数-@RequestParam

    第七篇->自己实现 SpringMVC 底层机制 系列之-实现任务阶段 7- 完成简单视图解析

    第八篇->自己实现 SpringMVC 底层机制 系列之-实现任务阶段 8- 完成返回 JSON 格式数据-@ResponseBody
                          
                          
    😁热门专栏推荐
    想学习vue的可以看看这个

    java基础合集

    数据库合集

    redis合集

    nginx合集

    linux合集

    等等等还有许多优秀的合集在主页等着大家的光顾感谢大家的支持

    🤔欢迎大家加入我的社区 尘觉社区

    文章到这里就结束了,如果有什么疑问的地方请指出,诸佬们一起来评论区一起讨论😁
    希望能和诸佬们一起努力,今后我们一起观看感谢您的阅读🍻
    如果帮助到您不妨3连支持一下,创造不易您们的支持是我的动力🤞

  • 相关阅读:
    jvm参数配置
    (4) OpenCV图像处理kNN近邻算法-识别数字0和1
    【Linux】在 Ubuntu 系统下使用 Screen 运行 Python 脚本
    [vscode]使用cmake时将命令行参数传递给调试目标
    【0907 C高级day2】Shell脚本
    Cy3-PEG-OH,Cy3-聚乙二醇-羟基,OH/COOH/NH2/NHS-PEG-Cy3
    数据库管理-第四十四期 数据库的物理隔离(20221118)
    PX4模块设计之二十八:RCInput模块
    突破tls/ja3新轮子
    大数据概论总结
  • 原文地址:https://blog.csdn.net/apple_67445472/article/details/132424784