Spring - 手写模拟Spring底层原理

news2024/11/26 15:25:40

手写Spring

定义配置类AppConfig

@ComponentScan("com.spring.zsj")
public class AppConfig {

    @Bean
    public ApplicationListener applicationListener() {
        return new ApplicationListener() {
            @Override
            public void onApplicationEvent(ApplicationEvent event) {
                System.out.println("接收到了一个事件"+event );
            }
        };
    }

}

定义容器ZSJApplicationContext

public class ZSJApplicationContext {

    private Class configClass;

    private Map<String,BeanDefinition> beanDefinitionMap =new HashMap<>();//bean定义

    private Map<String,Object> singleObjects = new HashMap<>(); //单例池

    private List<BeanPostProcessor> beanPostProcessorList =new ArrayList<>(); //后置处理

    public ZSJApplicationContext(Class configClass)  {
        this.configClass = configClass;
        scanComponent(configClass);

        //找出单例bean
        for (Map.Entry<String,BeanDefinition> entry: beanDefinitionMap.entrySet()
             ) {
            String beanName = entry.getKey();
            BeanDefinition beanDefinition = entry.getValue();
            if(beanDefinition.equals("singleton")){
                Object bean = createBean(beanName, beanDefinition);
                singleObjects.put(beanName,bean);
            }
        }
    }


    private Object createBean(String beanName,BeanDefinition beanDefinition){
        Class clazz = beanDefinition.getType();
        Object newInstance = null;
        try {
            newInstance =  clazz.getConstructor().newInstance();

            //依赖注入
            for (Field field : clazz.getDeclaredFields()) {
                if (clazz.isAnnotationPresent(Autowired.class)) {
                    field.setAccessible(true);
                    field.set(newInstance, getBean(field.getName()));
                }
            }

            //执行回调方法
            if (newInstance instanceof  BeanNameAware){
                ((BeanNameAware) newInstance).setBeanName(beanName);
            }


            //执行初始化前的方法
            for (BeanPostProcessor beanPostProcessor: beanPostProcessorList) {
                newInstance = beanPostProcessor.postProcessBeforeInitialization(newInstance, beanName);
            }

            //当前对象是否实例化了
            if(newInstance instanceof  InitializingBean){
                ((InitializingBean) newInstance).afterPropertiesSet();
            }

            //执行初始化后的方法(例如Aop)
            for (BeanPostProcessor beanPostProcessor: beanPostProcessorList) {
                newInstance = beanPostProcessor.postProcessAfterInitialization(newInstance, beanName);
            }


        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return newInstance;
    }

    private void scanComponent(Class configClass) {
        if(configClass.isAnnotationPresent(ComponentScan.class)){
            ComponentScan annotation =(ComponentScan) configClass.getAnnotation(ComponentScan.class);
            String path = annotation.value();

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

            ClassLoader classLoader = ZSJApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(path);

            File file = new File(resource.getFile());
            if(file.isDirectory()){//若是文件夹,则取出对应的文件
                for (File f: file.listFiles()) {
                    String absolutePath = f.getAbsolutePath();
                    //System.out.println(absolutePath);

                    String com = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
                    String replace = com.replace("\\", ".");
                   // System.out.println(replace);

                    try {
                        Class<?> clazz = classLoader.loadClass(replace);
                        if(clazz.isAnnotationPresent(Component.class)){

                            //clazz 是否实现了BeanPostProcessor接口
                            if(BeanPostProcessor.class.isAssignableFrom(clazz)){
                                BeanPostProcessor instance = (BeanPostProcessor)clazz.getConstructor().newInstance();
                                beanPostProcessorList.add(instance);
                            }

                            //获取bean 的名字
                            Component annotation1 = clazz.getAnnotation(Component.class);
                            String beanName = annotation1.value();
                            if("".equals(beanName)){
                                String name = Introspector.decapitalize(clazz.getSimpleName());
                            }


                            BeanDefinition beanDefinition = new BeanDefinition();
                            beanDefinition.setType(clazz);

                            if(clazz.isAnnotationPresent(Scope.class)){
                                //圆型的
                                Scope scope = clazz.getAnnotation(Scope.class);
                                String value = scope.value();
                                beanDefinition.setScope(value);
                            }else {
                                //单例的
                                beanDefinition.setScope("singleton");
                            }
                            beanDefinitionMap.put(beanName,beanDefinition);
                         //   System.out.println(clazz);
                        }
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }

                }
            }

         //   System.out.println(path);
        }
    }


    //通过bean名称获取bean对象
    public Object getBean(String beanName){

        if(!beanDefinitionMap.containsKey(beanName)){
                throw new NullPointerException();
        }

        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if(beanDefinition.getScope().equals("singleton")){
            Object singletonBean = singleObjects.get(beanName);
            if(singletonBean== null){
                singletonBean = createBean(beanName, beanDefinition);
                singleObjects.put(beanName,singletonBean);
            }
            return singletonBean;
        }else {
            //原型的
            Object prototypeBean = createBean(beanName, beanDefinition);
            return prototypeBean;
        }
    }
}

定义注解@Autowired  @Component  @Scope @ComponentScan

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







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




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





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

定义后置处理器BeanPostProcessor,用于初始化

public interface BeanPostProcessor {


    default Object postProcessBeforeInitialization(Object bean, String beanName)  {
        return bean;
    }


    default Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }
}

   定义ZSJBeanPostProcessor实现BeanPostProcesso

@Component
public class ZSJBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {

        if(beanName.equals("userService")){
            Object proxyInstance = Proxy.newProxyInstance(ZSJBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    //切面
                    System.out.println("切面逻辑");

                    return method.invoke(bean,args);
                }
            });
            return proxyInstance;
        }


        return bean;
    }
}

定义初始化接口InitializingBean

public interface InitializingBean {
    void afterPropertiesSet();
}

定义普通的类(可实例化成单例bean)

@Component("userService")
@Scope("singleton")
//public class UserService implements InitializingBean {
public class UserService implements UserInterface {

    @Autowired
    private OrderService orderService;



     @ZSanValue("zhangsan")
    private String user;

    //圆型bean 表示多例bean
    public void test(){
        System.out.println(orderService);
    }

//    @Override
//    public void afterPropertiesSet() {
//        System.out.println("初始化");
//    }
}

定义普通的类(可实例化成原型bean)

@Component("orderService")
@Scope("prototype")
public class OrderService {

    //圆型bean 表示多例bean
    public void test(){
        System.out.println("hello");
    }
}

定义启动类main


public class Test {
    public static void main(String[] args) {

        //非懒加载的单例bean
//        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
//        UserService userService = (UserService)context.getBean("userService");
//
//        userService.test();


        ZSJApplicationContext context = new ZSJApplicationContext(AppConfig.class);
       UserInterface userService = (UserInterface)context.getBean("userService");
        userService.test();

  //      System.out.println(context.getBean("userService"));
//        System.out.println(context.getBean("userService"));
//        System.out.println(context.getBean("userService"));
//        System.out.println(context.getBean("orderService"));
//        System.out.println(context.getBean("orderService"));
//        System.out.println(context.getBean("orderService"));


//        AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(context);
//        reader.register(User.class);
//        System.out.println(context.getBean("user"));


        StringToUserPropertyEditor propertyEditor = new StringToUserPropertyEditor();
        propertyEditor.setAsText("1");

        User value =new User();
        System.out.println(value);



    }
}

BeanPostProcesso扩展使用方法

自定义注解@ZSanValue

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

使用注解时,将注解的值赋给属性:如

@ZSanValue("zhangsan")
private String user;

 实现后置处理器,并执行初始化前的操作,将自定义的注解值进行属性赋值

@Component
public class ZSanValueBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {

        for (Field field : bean.getClass().getDeclaredFields()) {
            if(field.isAnnotationPresent(ZSanValue.class)){
                field.setAccessible(true);
                try {
                    field.set(bean,field.getAnnotation(ZSanValue.class).value());
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }


        return bean;
    }
}

回调方法使用BeanNameAware

定义回调接口

public interface BeanNameAware {
    
    void setBeanName(String name);
}

则实现类需要实现BeanNameAware接口

@Component("userService")
@Scope("singleton")
//public class UserService implements InitializingBean {
public class UserService implements UserInterface,BeanNameAware {

    @Autowired
    private OrderService orderService;

    @ZSanValue("zhangsan")
    private String user;


    private String beanName;


    //圆型bean 表示多例bean
    public void test(){
        System.out.println(orderService);
    }

    @Override
    public void setBeanName(String name) {
       this.beanName=name;
    }

//    @Override
//    public void afterPropertiesSet() {
//        System.out.println("初始化");
//    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

yolov7模型轻量化改进之MobileOne骨干替换

本文在之前文章yolov7分割训练的基础上进行改进: https://blog.csdn.net/qq_41920323/article/details/129464115?spm=1001.2014.3001.5502 具体GitHub工程下载,环境安装配置,数据准备等,请借鉴之前的文章,此处只介绍如何进行改进。 MobileOne地址:https://github.com…

【算法|滑动窗口No.3】leetcode3. 无重复字符的最长子串

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…

Nignx安装负载均衡动静分离以及Linux前端项目部署将域名映射到特定IP地址

目录 一、nginx简介 1.1 定义 1.2 背景 1.3 作用 二、nginx搭载负载均衡提供前后分离后台接口数据 2.1 nginx安装 2.1.1 下载依赖 2.1.2 下载并解压安装包 2.1.3 安装nginx 2.1.4 启动nginx服务 2.2 tomcat负载均衡 2.2.1 负载均衡所需服务器准备 2.2.2 配置修改 …

内网穿透入门

内网穿透 内网穿透&#xff08;英文&#xff1a;Port Forwarding&#xff09;是一种网络技术&#xff0c;用于将公共互联网&#xff08;外网&#xff09;的请求转发到私有局域网&#xff08;内网&#xff09;中的特定设备或服务。在许多情况下&#xff0c;设备或服务位于一个局…

负载均衡深度解析:算法、策略与Nginx实践

引言 如今&#xff0c;网站和应用服务面临着巨大的访问流量&#xff0c;如何高效、稳定地处理这些流量成为了一个亟待解决的问题。负载均衡技术因此应运而生&#xff0c;它通过将流量合理分配到多个服务器上&#xff0c;不仅优化了资源的利用率&#xff0c;还大大提升了系统的…

下载树莓派对应的64位Ubuntu系统步骤

说点废话&#xff1a;因为ros2需要安装在64位Ubuntu上面&#xff0c;所以安装64位最合适&#xff1b; 第一步打开https://cn.ubuntu.com/ 网站&#xff1b;选择下载--->iot----> 选择这个镜像文件下载。我觉得镜像文件是img格式的&#xff0c;跟iso文件区别是&#xff…

牛客网刷题-(9)

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

VisualSVN initialization failed, For more details see Output window.

VisualSVN initialization failed, For more details see Output window. 通过输出窗口查看详细日志地址&#xff1a; 打开日志&#xff0c;发现报错信息为&#xff1a;Cannot get image ‘742477e2-c767-429f-b906-6c553b7cd1d1:12, 9x16’ from the image service. 原因&a…

Java17-20新特性

目录 一、Java17新特性 1、switch语法的变化(预览) 2、Sealed Classes 3、伪随机数的变化 4、去除了AOT和JIT 二、Java18新特性 1、默认使用UTF-8字符编码 2、简单的web服务器 3、将被移除的方法 4、snippet注解 三、Java19新特性 1、Virtual Threads(Preview)虚拟…

vue图书馆书目推荐数据分析与可视化-计算机毕业设计python-django-php

建立本图书馆书目推荐数据分析是为了通过系统对图书数据根据算法进行的分析好推荐&#xff0c;以方便用户对自己所需图书信息的查询&#xff0c;根据不同的算法机制推荐给不同用户不同的图书&#xff0c;用户便可以从系统中获得图书信息信息。 对用户相关数据进行分析&#xff…

Flutter 05 组件状态、生命周期、数据传递(共享)、Key

一、Android界面渲染流程UI树与FlutterUI树的设计思路对比 二、Widget组件生命周期详解 1、Widget组件生命周期 和其他的视图框架比如android的Activity一样&#xff0c;flutter中的视图Widget也存在生命周期&#xff0c;生命周期的回调函数体现在了State上面。组件State的生命…

python自动化测试(九):EcShop添加商品功能

前置条件&#xff1a; 本地部署&#xff1a;ECShop的版本是3.0.0、Google版本是 Google Chrome65.0.3325.162 (正式版本) &#xff08;32 位&#xff09; py的selenium版本是3.11.0 目录 一、前置代码 二、添加商品操作 2.1 点击添加商品 2.2 添加名称、分类、品牌 2…

Java基础知识梳理(万字解析)

目录 数据类型 变量和常量 变量的命名规范 局部变量 类变量 实例变量 常量 运算符 java程序流程控制 Scanner类简单用法 方法 数组 面向对象Object-Oriented Programming&#xff08;OOP&#xff09; 类 对象 封装 继承 extends 多态 抽象 abstract 接口 i…

CSS3弹性布局

2009年&#xff0c;W3C提出一种崭新的布局方案—弹性盒(Flexbox)布局&#xff0c;使用该模型可以轻松地创建自适应窗口的流动布局&#xff0c;或者自适应字体大小的弹性布局。W3C的弹性盒布局分为旧版本、新版本及混合过渡版本3种不同的设计方案&#xff0c;其中混合过渡版本主…

「专题速递」数据驱动赋能、赛事直播优化、RTC技术、低延时传输引擎、多媒体处理框架、GPU加速...

点击文末阅读原文&#xff0c; 免费报名【抖音背后的体验增长实战揭秘】专场 随着全行业视频化的演进&#xff0c;营销、知识、商业和空间的交互体验正在被重塑。这种变化不仅仅是一种抽象的趋势&#xff0c;更是关系到用户留存和业务增长的关键因素。面对这样的挑战&#xff0…

技术报告模板:2023年全国大学生电子设计竞赛:运动目标控制与自动追踪系统(E题)

2023年全国大学生电子设计竞赛 运动目标控制与自动追踪系统&#xff08;E题&#xff09; 2023年8月4日 摘要&#xff1a;针对本题目的各项要求&#xff0c;本研究采用软硬件结合的方法设计了一套运动目标控制与自动追踪系统。该系统由OpenMV嵌入式计算机视觉平台、STM32单片机控…

[PHP]pearProject协作系统 v2.8.14 前后端

pearProject是一款轻量级的在线项目/任务协作系统&#xff0c;远程办公协作。 概述 PearProject 不支持 IE8 及以下版本&#xff0c;建议使用基于Webkit内核的现代浏览器访问 PearProject 为前后端分离架构&#xff0c;因此安装分为后端和前端两大部分&#xff0c;需要分别进…

定时器PWM输出

目录 介绍 PWM占空比 框图 输出比较 通道 1 输出比较功能为例 PWM 输出模式 PWM 边沿对齐模式 hal库代码 标准库代码 介绍 脉冲宽度调制(PWM)&#xff0c;是英文“Pulse Width Modulation”的缩写&#xff0c;简称脉宽调制&#xff0c;是利用微 处理器的数字输出来对模…

Android启动优化-全文详细

一个应用App的启动速度能够影响用户的首次体验&#xff0c;通常用户期望app响应和加载速度越快越好。一个启动速度慢的app很可能会给用户留下不好的印象&#xff0c;除了导致用户在应用市场上的打分低之外&#xff0c;很有可能导致致用户直接卸载。这种糟糕的体验可能会导致用户…

[译]CSS Animations 与 CSS Transitions

本文译者为 360 奇舞团前端开发工程师原文标题&#xff1a;CSS Animations Versus CSS Transitions原文作者&#xff1a;Kirupa Chinnathambi原文出处&#xff1a;《Creating Web Animations: Bringing Your UIs to Life》 在 CSS 中有两种设置动画的方式即 CSS animations 和 …