Spring6学习技术|IoC|手写IoC

学习材料

尚硅谷Spring零基础入门到进阶,一套搞定spring6全套视频教程(源码级讲解)

有关反射的知识回顾

IoC是基于反射机制实现的。

Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。简单来说,反射机制指的是程序在运行时能够获取自身的信息。

要想解剖一个类,必须先要获取到该类的Class对象。而剖析一个类或用反射解决具体的问题就是使用相关API(1)java.lang.Class(2)java.lang.reflect,所以,Class对象是反射的根源

具体要掌握的操作就是如何获取class(三种方法),如何获取构造器及创建对象,如何获取属性,如何获取方法并执行。(这里注意public和private的不同操作)。

package com.zy.reflect;

import org.testng.annotations.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class TestCar {
    @Test
    public void test01() throws Exception {
        //获取class的方法
//        Car car = new Car();
//        Class clazz1 = car.getClass();

        Class clazz2 = Car.class;

        Class clazz3 = Class.forName("com.zy.reflect.Car");

        Constructor[] constructors = clazz3.getDeclaredConstructors();
        for(Constructor con:constructors){
            if(con.getParameterCount()==3){
                con.setAccessible(true);
                Car car = (Car) con.newInstance("奔驰", 1, "黑色");
//                System.out.println(car);
            }
        }
        //或者直接获取
        Constructor c2 = clazz3.getDeclaredConstructor(String.class, Integer.class, String.class);
        c2.setAccessible(true);
        Car car2 = (Car)c2.newInstance("捷达", 15, "白色");
        System.out.println(car2);

    }
    @Test
    public void test02() throws Exception {

        Class clazz3 = Class.forName("com.zy.reflect.Car");
        Car car = (Car)clazz3.getConstructor().newInstance();
        Field[] fields = clazz3.getDeclaredFields();
        for (Field field:fields) {
            if(field.getName().equals("name")) {
                //设置允许访问
                field.setAccessible(true);
                field.set(car,"五菱宏光");//这里需要有对应的对象。
                System.out.println(car);
            }
            System.out.println(field.getName());

        }


    }
    @Test
    public void test03() throws Exception {

        Class clazz3 = Class.forName("com.zy.reflect.Car");
        Car car = (Car)clazz3.getConstructor().newInstance();
        Method[] methods = clazz3.getDeclaredMethods();
        for (Method method:methods) {

            //执行方法 toString
            if(method.getName().equals("toString")) {
                String invoke = (String)method.invoke(car);
                System.out.println("toString执行了:"+invoke);
            }
            if(method.getName().equals("run")) {
                //设置允许访问
                method.setAccessible(true);
                method.invoke(car);//这里需要有对应的对象。
                System.out.println(car);
            }
        }
    }
}

手写IoC

实现的思路设计
在这里插入图片描述
环境框架
在这里插入图片描述

第一二步手打过很多次了,没什么难度。
第三步:
创建Annotation文件,与接口之类的类似。不同在于有元注解需要考虑(注解面向的范围)Bean是创建类,Di注入

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Bean {
}

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Di {
}

第四步:要了解这一步要干嘛,需要从需求出发。
需求如下:即输入一个com.zy。我要组织得到一个Map集合,创建好所有标注注解Bean的类,与Di注入。getBean用于利用class信息返回Map内的元素。

public class TestUser {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationApplicationContext("com.zy");
        UserService bean = (UserService)context.getBean(UserService.class);
        bean.add();

    }
}

如何实现创建Map(主要学习的是如何遍历文件,如何扫描注解)

private Map<Class, Object> beanFactory = new HashMap<>();
    private static String rootPath;
    @Override
    public Object getBean(Class clazz) {
        return beanFactory.get(clazz);
    }
public AnnotationApplicationContext(String basePackage) {
        //如何根据包的路径,设置扫描规则
        try {
            String packageDirName = basePackage.replaceAll("\\.", "\\\\");
            Enumeration<URL> dirs =Thread.currentThread().getContextClassLoader().getResources(packageDirName);
            while (dirs.hasMoreElements()) {
                URL url = dirs.nextElement();
                String filePath = URLDecoder.decode(url.getFile(),"utf-8");
//                System.out.println(filePath);
                //包扫描
                rootPath = filePath.substring(0, filePath.length()-packageDirName.length());
                loadBean(new File(filePath));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        //属性注入
        loadDi();

    }

    private void loadBean(File file) throws Exception {
        //1.当前FIle是否是文件夹
        if (file.isDirectory()){
            //2.是文件夹的话,获取所有内容
            File[] childrenFiles = file.listFiles();
            //3.判断内容是否为空
            if (childrenFiles == null || childrenFiles.length==0){
                return;
            }
            //4.遍历所有内容
            for (File child:childrenFiles){
                //1.还是文件夹就递归
                if (child.isDirectory()){
                    loadBean(child);
                }else {
                    //是文件,获取完整的类路径
                    String pathWithClass = child.getAbsolutePath().substring(rootPath.length()-1);
                    //是不是class文件
                    if (pathWithClass.contains(".class")){
                        String allName = pathWithClass.replaceAll("\\\\", "\\.").replace(".class", "");
                        //判断类中有没有@Bean注解
                        Class<?> clazz = Class.forName(allName);
                        if (!clazz.isInterface()){
                            Bean annotation = (Bean)clazz.getAnnotation(Bean.class);
                            if (annotation!=null){
                                Object instance = clazz.getConstructor().newInstance();
                                if (clazz.getInterfaces().length>0){
                                    beanFactory.put(clazz.getInterfaces()[0], instance);
                                }else{
                                    beanFactory.put(clazz, instance);
                                }
                            }

                        }

                    }


                }

            }


        }

    }
    private void loadDi(){
        //实例化对象在beanFactory的map
        //1 遍历beanFactory的map
        Set<Map.Entry<Class, Object>> entries = beanFactory.entrySet();
        for(Map.Entry<Class, Object> entry:entries){
            //2 获取map的每个对象value,每个对象属性获取到
            Object obj = entry.getValue();
            Class clazz = obj.getClass();
            Field[] fields = clazz.getDeclaredFields();
            //3 遍历得到每个对象属性数组,得到每个属性
            for(Field field:fields){
                //4 判断属性上面是都有@Di注解
                Di annotation = field.getAnnotation(Di.class);
                //5 如果有@Di注解,把对象进行设置(注入)
                if (annotation!=null){
                    field.setAccessible(true);
                    //这一步什么??filed这个属性的类型field.getType() beanFactory.get()得到对应的对象。
                    try {
                        field.set(obj, beanFactory.get(field.getType()));
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(e);
                    }
                }
            
        }

    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/399982.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

P2957 [USACO09OCT] Barn Echoes G

P2957 [USACO09OCT] Barn Echoes G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P2957 题目分析 对于求单个字符串的哈希值相当于求前缀和&#xff0c;而求单个字符串的子串的哈希值则相当于求其区间和&#xff1b; 那么只需求两个…

面试经典150题——旋转图像

"You are never too old to set another goal or to dream a new dream." - C.S. Lewis​ 1. 题目描述 2. 题目分析与解析 2.1 思路一 还是最简单的尝试模拟人的思维&#xff0c;如果对于一个普通人解决该题目&#xff0c;那就是先把第一行放在最后一列 或者 把第…

入职字节外包才一个月,我就离职了

有一种打工人的羡慕&#xff0c;叫做“大厂”。 真是年少不知大厂香&#xff0c;错把青春插稻秧。 但是&#xff0c;在深圳有一群比大厂员工更庞大的群体&#xff0c;他们顶着大厂的“名”&#xff0c;做着大厂的工作&#xff0c;还可以享受大厂的伙食&#xff0c;却没有大厂…

惠尔顿 网络安全审计系统 任意文件读取漏洞复现

0x01 产品简介 惠尔顿网络安全审计产品致力于满足军工四证、军工保密室建设、国家涉密网络建设的审计要求&#xff0c;规范网络行为&#xff0c;满足国家的规范&#xff1b;支持1-3线路的internet接入、1-3对网桥&#xff1b;含强大的上网行为管理、审计、监控模块&#xff1b…

猫毛过敏不能养猫了吗?除猫毛好的宠物空气净化器品牌有哪些?

让我们来探讨一下如何让容易过敏的家庭成员和猫咪更好地相处。很多人喜欢猫咪&#xff0c;但与它们相处一段时间后&#xff0c;可能会出现鼻塞、喷嚏和眼泪不断的过敏症状。那么&#xff0c;为什么会过敏呢&#xff1f;这是因为猫的唾液中含有Fel d1蛋白质&#xff0c;当它们舔…

回显服务器的制作方法

文章目录 客户端和服务器TCP和UDP的特点UDP socket api的使用DatagramSocketDatagramPacketInetSocketAddress API 做一个简单的回显服务器UDP版本的回显服务器TCP版本的回显服务器 客户端和服务器 在网络中&#xff0c;主动发起通信的一方是客户端&#xff0c;被动接受的这一方…

SpringBoot+Vue+MySQL:图书管理系统的技术革新

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

怀孕了要把猫送走吗?推荐一款吸猫毛神器—宠物空气净化器

相信大部分家庭都会遇到这样一个二选一的难题&#xff1a;怀孕了还能养猫吗&#xff1f;还是要把猫送走&#xff1f; 许多人担心在孕期与宠物接触可能会导致健康问题&#xff0c;主要是因为弓形虫的存在。然而&#xff0c;实际上感染弓形虫并不容易。如果你真的很担心&#xf…

绘图神器VisIt初步使用

文章目录 安装绘图图像属性 VisIt是一款用于可视化科学数据的开源软件&#xff0c;适用于大型数据集&#xff0c;并提供了丰富的可视化和分析功能。 安装 首先下载VisIt&#xff0c;然后下载一些示例以及测试数据&#xff0c;地址在github上。 下载之后安装&#xff0c;有两…

基于Python的热点分析预警系统

项目&#xff1a;基于Python的热点分析预警系统 摘 要 基于网络爬虫的数据可视化服务系统是一种能自动从网络上收集信息的工具&#xff0c;可根据用户的需求定向采集特定数据信息的工具&#xff0c;本项目通过研究爬取微博网来实现微博热点分析数据信息可视化系统功能。对于采…

二叉搜索树(二叉排序树、二叉查找树)

二叉搜索树&#xff08;二叉排序树、二叉查找树&#xff09; 一、定义二、操作&#xff08;一&#xff09;中序遍历&#xff08;二&#xff09;查找&#xff08;三&#xff09;插入&#xff08;四&#xff09;删除 三、二叉搜索树的应用四、二叉搜索树操作的性能分析五、总结 一…

CCF-B类SGP‘24 4月10日截稿!速速行动!

会议之眼 快讯 第22届SGP(Eurographics Symposium on Geometry Processing)即欧洲图形学几何处理专题讨论会将于 2024 年 6月24 -日至26日在美国麻省理工学院举行&#xff01;SGP是传播几何处理新研究想法和尖端成果的首要学术会议。作为该领域的重要学术盛事&#xff0c;SGP会…

模型转换案例学习:等效替换不支持算子

文章介绍 Qualcomm Neural Processing SDK &#xff08;以下简称SNPE&#xff09;支持Caffe、ONNX、PyTorch和TensorFlow等不同ML框架的算子。对于某些特定的不支持的算子&#xff0c;我们介绍一种算子等效替换的方法来完成模型转换。本案例来源于https://github.com/quic/qidk…

从零开始手写mmo游戏从框架到爆炸(十六)— 客户端指定回调路由与登录

导航&#xff1a;从零开始手写mmo游戏从框架到爆炸&#xff08;零&#xff09;—— 导航-CSDN博客 我们这次来把注册、登录、选择英雄&#xff0c;进入主页-选择地图的功能完善。 在这之前&#xff0c;我们还要解决一个问题&#xff0c;就是服务端往客户端发消息的路由问题…

CSS 不同颜色的小圆角方块组成的旋转加载动画

<template><!-- 创建一个装载自定义旋转加载动画的容器 --><view class="spinner"><!-- 定义外部包裹容器,用于实现整体旋转动画 --><view class="outer"><!-- 定义四个内部小方块以形成十字形结构 --><view clas…

vtk.js加载dicom,获取世界点的坐标、两点之间的距离

通过点击vtk的renderWindow&#xff0c;获取坐标点。 获取点的坐标有vtkCellPicker和vtkPointPicker两个方法&#xff0c;区别在于vtkCellPicker可以区分是否点击在模型上&#xff0c;推荐使用vtkCellPicker。 获取两点之间距离使用vtkMath的方法&#xff0c;vtkMath.distance…

阿里云k8s容器部署consul集群的高可用方案

一、背景 原本consul集群是由三个server节点搭建的&#xff0c;购买的是三个ecs服务器&#xff0c; java服务在注册到consul的时候&#xff0c;随便选择其中一个节点。 从上图可以看出&#xff0c; consul-01有28个服务注册&#xff0c;而consul-02有94个服务&#xff0c;co…

一凸包----------12,分而治之(2)

在上节中&#xff0c;两部分子凸包有重合的部分&#xff0c;不简洁。这一节是沿着某个方向&#xff0c;子凸包不重叠&#xff0c;如下图 根据以前的方法&#xff0c;很可能认为是两个子凸包上顶点与上顶点相连&#xff0c;下顶点与下顶点相连&#xff0c;形成两条支撑线&#…

算法沉淀——二叉树中的深搜(leetcode真题剖析)

算法沉淀——二叉树中的深搜 01.计算布尔二叉树的值02.求根节点到叶节点数字之和03.二叉树剪枝04.验证二叉搜索树05.二叉搜索树中第K小的元素06.二叉树的所有路径 二叉树的深度优先搜索是一种遍历二叉树的方法&#xff0c;它通过深度递归的方式探索树的结构。有两种主要形式&am…

ubuntu 22.04 图文安装

ubuntu 22.04.3 live server图文安装 一、在Vmware里安装ubuntu 22.04.3 live server操作系统 选择第一个选项开始安装 选择English语言 选择中间选项不更新安装&#xff0c;这是因为后续通过更换源之后再更新会比较快 键盘设计继续选择英文&#xff0c;可以通过语言选择…