java-spring 图灵 02 手写spring

01.idea中创建一个maven管理的空项目
在这里插入图片描述
02.模拟创建出spring容器类,这里叫wzpApplicationContext,创建的时候会自动加载配置类的数据

public class wzpApplicationContext {
    private Class configClass;

    public wzpApplicationContext(Class configClass) {
        this.configClass = configClass;
    }
}

模拟出容器类要扫描的配置类Appconfig

public class Appconfig {
}

在test中去测试这些创建的类

public class Mytest {
 public static void main(String[] args) {
    wzpApplicationContext wzpApplicationContext=new wzpApplicationContext(Appconfig.class);
}
}

03.在wzpApplicationContext 添加getbean函数,获取spring容器中的bean

  public Object getBean(String beanName) {
        return null;
    }

创建服务类UserService

public class UserService {
}

在这里插入图片描述

在测试test中运行getbean方法

public class Mytest {
 public static void main(String[] args) {
    wzpApplicationContext wzpApplicationContext=new wzpApplicationContext(Appconfig.class);

    UserService userService=   (UserService)wzpApplicationContext.getBean("UserService");
}
}

04.在服务类中写一些方法,等会看一下是不是可以运行

public class UserService {
    public void test(){
        System.out.println("test");
    }
}

此时在test中:

public class Mytest {
    public static void main(String[] args) {
        wzpApplicationContext wzpApplicationContext=new wzpApplicationContext(Appconfig.class);

        UserService userService=   (UserService)wzpApplicationContext.getBean("UserService");

        userService.test();
    }

}

05.写几个自定义的注解
比如说,spring容器中的扫描,需要注解@ComponentScan
在这里插入图片描述

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

    String value() default "";
}

解释一下:
Target 注解是说,这个注解主要用在哪一个区域,TYPE表示类,FIELD表示属性,METHOD表示方法。
Rentention 注解是说,这个注解在那个阶段使用,RUNTIME是在类加载阶段使用

然后模仿spring去用:

@ComponentScan("org.example.wzp.service")
public class Appconfig {
    
}

再创建一个注解:@Component

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
    String value() default "";
}

在服务类中去使用:

@Component
public class UserService {
    public void test(){
        System.out.println("test");
    }
}

06.实现扫描的功能
现在只是写了几个注解,具体的功能代码还没有写,接下来就是扫描的代码
回想spring框架,是创建spring容器的时候,就会自动创建bean
所以,扫描的具体实现代码就应该在构造函数中写


        //判断类上是不是有注解ComponentScan

        if(configClass.isAnnotationPresent(ComponentScan.class)){

            //获取注解对象

            ComponentScan componentScan = (ComponentScan)configClass.getAnnotation(ComponentScan.class);

            //获取注解对象上的value,这里也就是path
            String path = componentScan.value();

            //文件的路径是/,而获取到的是带有.的包名

            path.replace(".","/");

            //获取当前的类加载器
            ClassLoader classLoader = wzpApplicationContext.class.getClassLoader();
            //根据类加载器获取编译完成的target的class文件夹的路径

            URL resource = classLoader.getResource(path);
            //根据路径,获取文件

            File file=new File(resource.getFile());
            //因为扫描的是包,所以大概率是一个目录

            if (file.isDirectory()){
                //获取目录中的文件集合

                for (File f:file.listFiles()){
                    //获取文件的绝对路径
                    String absolutePath = f.getAbsolutePath();
                    //截取从org到class
                    String org = absolutePath.substring(absolutePath.indexOf("org"), absolutePath.indexOf(".class"));
                    //由于是文件路径,要转换回来,把\变成 . 包名,好让类加载器加载得到类的对象
                    String classpath = org.replace("\\", ".");
                    //加载器加载后,得到一个类对象
                    Class<?> aClass = classLoader.loadClass(classpath);
                    //判断是不是类上存在Component注解
                    if(aClass.isAnnotationPresent(Component.class)){

                    //判断是不是单例模式,要看自定义的注解Scope
                        if (aClass.isAnnotationPresent(Scope.class)){
                            Scope scopeAnnotation = aClass.getAnnotation(Scope.class);

                            String value = scopeAnnotation.value();

                            if (value.equals("singleton")){
                                //创建单例模式的bean
                            }
                            else{
                                //多例模式
                            }

                        }
                    }

                }
            }

        }
    }

创建一个注解 Scope

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {
    String value() default "";
}

在服务类上使用,如果是单例,就写singleton,如果是多例,就写prototype

例如:服务类UserService ,这里声明是单例模式

@Component("UserService")
@Scope("singleton")
public class UserService {
    public void test(){
        System.out.println("test");
    }
}

07.优化设计,把类上注解的许多信息都放入到一个对象中的话,直接去读取这个类的属性就好了

创建一个BeanDefinition

public class BeanDefinition {
  
     private Class type;
     private String scope;
     private Boolean isLazy;

     public Class getType() {
          return type;
     }

     public void setType(Class type) {
          this.type = type;
     }

     public String getScope() {
          return scope;
     }

     public void setScope(String scope) {
          this.scope = scope;
     }

     public Boolean getLazy() {
          return isLazy;
     }

     public void setLazy(Boolean lazy) {
          isLazy = lazy;
     }

}


再次优化扫描

 //判断是不是类上存在Component注解
                    if(aClass.isAnnotationPresent(Component.class)){
                    
                        Component componentAnnotation = aClass.getAnnotation(Component.class);

                        String name = componentAnnotation.value();


                        BeanDefinition beanDefinition=new BeanDefinition();

                        beanDefinition.setType(aClass);
                    //判断是不是单例模式,要看自定义的注解Scope
                        if (aClass.isAnnotationPresent(Scope.class)){
                            Scope scopeAnnotation = aClass.getAnnotation(Scope.class);

                            String value = scopeAnnotation.value();
                            
                            beanDefinition.setScope(value);

                            if (value.equals("singleton")){
                                //创建单例模式的bean
                                beanDefinition.setScope("singleton");
                            }
                            else{
                                //多例模式
                            }

                        }
                    }

在wzpApplicationContext 中添加一个属性,map集合

public class wzpApplicationContext {
//配置类
    private Class configClass;
//存放BeanDefinition
    private Map<String,BeanDefinition> BeanDefinitionMap =new HashMap<>();
    }

把刚刚创建的BeanDefinition放入到map集合中:

if(aClass.isAnnotationPresent(Component.class)){

                        Component componentAnnotation = aClass.getAnnotation(Component.class);

                        String name = componentAnnotation.value();

                        BeanDefinition beanDefinition=new BeanDefinition();

                        beanDefinition.setType(aClass);
                    //判断是不是单例模式,要看自定义的注解Scope
                        if (aClass.isAnnotationPresent(Scope.class)){
                            Scope scopeAnnotation = aClass.getAnnotation(Scope.class);

                            String value = scopeAnnotation.value();

                            beanDefinition.setScope(value);

                            if (value.equals("singleton")){
                                //创建单例模式的bean
                                beanDefinition.setScope("singleton");
                            }
                            else{
                                //多例模式
                            }
                            BeanDefinitionMap.put(name,beanDefinition);

                        }
                    }

最后总的代码抽象此外一个方法:
在这里插入图片描述

   public wzpApplicationContext(Class configClass) throws ClassNotFoundException {
        this.configClass = configClass;


        //判断类上是不是有注解ComponentScan

        scan(configClass);
    }

   private void scan(Class configClass) throws ClassNotFoundException {
        if(configClass.isAnnotationPresent(ComponentScan.class)){

            //获取注解对象

            ComponentScan componentScan = (ComponentScan) configClass.getAnnotation(ComponentScan.class);

            //获取注解对象上的value,这里也就是path
            String path = componentScan.value();

            //文件的路径是/,而获取到的是带有.的包名

            path.replace(".","/");

            //获取当前的类加载器
            ClassLoader classLoader = wzpApplicationContext.class.getClassLoader();
            //根据类加载器获取编译完成的target的class文件夹的路径

            URL resource = classLoader.getResource(path);
            //根据路径,获取文件

            File file=new File(resource.getFile());
            //因为扫描的是包,所以大概率是一个目录

            if (file.isDirectory()){
                //获取目录中的文件集合

                for (File f:file.listFiles()){
                    //获取文件的绝对路径
                    String absolutePath = f.getAbsolutePath();
                    //截取从org到class
                    String org = absolutePath.substring(absolutePath.indexOf("org"), absolutePath.indexOf(".class"));
                    //由于是文件路径,要转换回来,把\变成 . 包名,好让类加载器加载得到类的对象
                    String classpath = org.replace("\\", ".");
                    //加载器加载后,得到一个类对象
                    Class<?> aClass = classLoader.loadClass(classpath);
                    //判断是不是类上存在Component注解
                    if(aClass.isAnnotationPresent(Component.class)){

                        Component componentAnnotation = aClass.getAnnotation(Component.class);

                        String name = componentAnnotation.value();

                        BeanDefinition beanDefinition=new BeanDefinition();

                        beanDefinition.setType(aClass);
                    //判断是不是单例模式,要看自定义的注解Scope
                        if (aClass.isAnnotationPresent(Scope.class)){
                            Scope scopeAnnotation = aClass.getAnnotation(Scope.class);

                            String value = scopeAnnotation.value();

                            beanDefinition.setScope(value);

                            if (value.equals("singleton")){
                                //创建单例模式的bean
                                beanDefinition.setScope("singleton");
                            }
                            else{
                                //多例模式
                            }
                            BeanDefinitionMap.put(name,beanDefinition);

                        }
                    }

                }
            }

        }
    }

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

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

相关文章

Selenium+TestNG学习笔记

------------------TestNG-------------------- 1.层级 suite -》test-》class-》method 建议层级 class对应一个测试用例&#xff0c;suite对应一个测试集 2. testNG中的PO模式 3.运行多个测试类的测试用例 通过suite来进行管理;suite在testNG中可以通过xml 来进行编写管理…

多媒体互动装置如何助力智慧城市展厅的信息化建设?

随着现代化科技技术的发展&#xff0c;智慧城市的建设概念与实施也日益成熟&#xff0c;其中智慧城市展厅便是用于展示智慧城市理念、技术和规划的重要平台&#xff0c;而应用在其中的多媒体互动装置&#xff0c;更是起着重要的作用&#xff0c;它们能够让观众更直观地了解和体…

浅述.Net中的Hash算法(顺带对称、非对称算法)

【写在前面】 对称加密算法(只有一个私钥&#xff0c;比如DES【不推荐】、AES)&#xff1b; 非对称加密算法&#xff08;公钥与私钥&#xff0c;比如RSA&#xff09;&#xff1b; Hash算法也称为散列函数算法&#xff0c;任意长度的数据都转换为固定长度的字符串&#xff08…

关闭 SPI 会导致 WRPERR 错误的问题分析

1. 引言 在 STM32 的应用中&#xff0c;SPI 算是用的比较多的外设了&#xff0c;也是单片机最常见外设之一。客户说它执行了关闭 SPI 的代码&#xff0c;竟然会导致 Flash 中的 WRPERR 标志置位&#xff0c;致使应用碰到一些问题。这就奇怪了&#xff0c;SPI 和内部 Flash 看起…

中仕公考:三支一扶期满后有编制吗?

三支一扶两年的期限到达之后&#xff0c;会自动获得编制吗? 完成三支一扶项目的服务期限后&#xff0c;参与人员必须通过正式的考试才能获得编制&#xff0c;而并不是期满后自动获得编制。但是&#xff0c;三支一扶服务期满人员在参加公务员考试中可依照其身份享受加分的优惠…

h5应用如何适配移动端(干货总结)

h5应用如何适配移动端总结 前言一、简单场景搭建二、从哪些方面进行适配?1.对html中的meta标签进行适配2.清除默认样式3.使用全局变量去控制采用css值4.绝对单位相对化 前端必备工具推荐网站(免费图床、API和ChatAI等实用工具): http://luckycola.com.cn/ 前言 H5应用的开发是…

基于springboot实现视频网站管理系统【项目源码+论文说明】计算机毕业设计

基于springboot实现视频网站管理系统演示 摘要 使用旧方法对视频信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在视频信息的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问…

AndroidAutomotive模块介绍(一)整体介绍

前言 Android Automotive 是一个基本 Android 平台&#xff0c;可运行 IVI 系统中预安装的 Android 应用以及可选的第二方和第三方 Android 应用。 本系列文档将会系统的介绍 Android Automotive 的功能、架构、逻辑等。模块逻辑将从 应用api接口、系统服务、底层服务&#x…

2024.4.12每日一题

今天上午参加了蓝桥杯&#xff0c;只会暴力&#xff0c;还需努力学习 LeetCode 找到冠军 || 题目链接&#xff1a;2924. 找到冠军 II - 力扣&#xff08;LeetCode&#xff09; 题目描述 一场比赛中共有 n 支队伍&#xff0c;按从 0 到 n - 1 编号。每支队伍也是 有向无环图…

泰坦尼克号幸存者预测

泰坦尼克号幸存者预测 1、特征工程概述2、数据预处理3、特征选择与提取4、建模与预测 1、特征工程概述 在上篇 泰坦尼克号幸存者数据分析 中&#xff0c;我们对泰坦尼克号的幸存者做了数据分析&#xff0c;通过性别、年龄、船舱等级等不同维度对幸存者进行了分类统计&#xff0…

Traefik的前世今生

Traefik 是一款现代的反向代理和负载均衡器&#xff0c;它的设计专门针对微服务架构和容器技术&#xff0c;如 Docker &#x1f433; 和 Kubernetes &#x1f3af;。自从其首次发布以来&#xff0c;Traefik 已经迅速成为云原生生态系统中不可或缺的一部分。在这篇文章中&#x…

上位机图像处理和嵌入式模块部署(qmacvisual缺失的颜色检测)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 在图像处理当中&#xff0c;对颜色的处理是非常重要的。当然&#xff0c;这要建立在拍摄图片是彩色图片的基础之上。工业上面&#xff0c;虽然是黑…

第三次作业

创建了一个教务管理系统的登录页面&#xff0c;其中包含左侧的图片以及右侧的表单容器&#xff0c;当鼠标悬停在表单容器上时&#xff0c;会稍微变大&#xff0c;并且图片容器会相应的缩小&#xff0c;是通过css的transition以及fiex属性实现。 表单容器包含用户名和密码的输入…

基于linux进一步理解核间通讯

芯片架构分为同构和异构: 如下图TC397: 如下图TDA4: 如下图STM32MP157: 非对称多处理结构(AMP): AMP 结构是指每个内核运行自己的 OS 或同一 OS 的独立实例&#

番茄 abogus rpc调用

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01;wx a15018601872 本文章…

生产者和消费者模型 | 阻塞队列 | 信号量 | 环形队列

文章目录 1.生产者和消费者模型2.生产者和消费者模型优点3.阻塞队列4.POSIX信号量5.基于环形队列的生产消费模型 本文完整的代码放在了这&#xff1a; Gitee链接 1.生产者和消费者模型 生产者和消费者模型&#xff0c;概括起来其实是一个321原则&#xff1a;3是&#xff1a;三…

如何恢复未保存或删除/丢失的Word文件?

关闭 Word 应用程序而不保存文档&#xff1f;误删Word文档&#xff1f;许多用户会在不同的情况下丢失Word文档。如果不幸遇到此类问题&#xff0c;如何恢复已删除或未保存的 Word 文档&#xff1f;有一些方法可以恢复未保存/删除的文档。此外&#xff0c;您还可以使用Word文件恢…

前端 接口返回来的照片太大 加载慢如何解决

现象 解决 1. 添加图片懒加载 背景图懒加载 对背景图懒加载做的解释 和图片懒加载不同&#xff0c;背景图懒加载需要使用 v-lazy:background-image&#xff0c;值设置为背景图片的地址&#xff0c;需要注意的是必须声明容器高度。 <div v-for"img in imageList&quo…

【论文笔记】PointMamba: A Simple State Space Model for Point Cloud Analysis

原文链接&#xff1a;https://arxiv.org/abs/2402.10739 1. 引言 基于Transformer的点云分析方法有二次时空复杂度&#xff0c;一些方法通过限制感受野降低计算。这引出了一个问题&#xff1a;如何设计方法实现线性复杂度并有全局感受野。 状态空间模型&#xff08;SSM&…

微服务-2 Eureka

Eureka 启动页面&#xff1a; 同理再注册完order-service后&#xff0c;刷新启动页面&#xff1a; userservice 启动多台服务&#xff1a; [ 代码 ]&#xff1a;orderService.java&#xff08;用 RestTemplate 调其他服务&#xff0c;用 userservice 代替 localhost:8081&…