返回顶部
首页 > 资讯 > 后端开发 > Python >SpringBoot实现使用反射模拟IOC和getBean
  • 424
分享到

SpringBoot实现使用反射模拟IOC和getBean

SpringBoot反射模拟IOCSpringBoot反射模拟getBean 2023-05-14 08:05:47 424人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

ioc就是spring的核心思想之一:控制反转。这里不再赘述,看我的文章即可了解: spring基础思想ioC 其次就是java的反射,反射机制是spring的重要实现核心,今天我看

ioc就是spring的核心思想之一:控制反转。这里不再赘述,看我的文章即可了解:

spring基础思想ioC

其次就是java的反射,反射机制是spring的重要实现核心,今天我看spring的三级缓存解决循坏引用的问题时,发现一个bean的生命周期与java对象的产生流程具备高度相似性,接着我就去重温了一下bean的创建流程,发现一个bean实例从无到有经历的过程非常有意思,spring用极其优雅的代码实现了用反射和各种map数据结构实现了bean的流水线式生产,非常优雅,于是我就尝试用反射写一个逆向生成实例对象的小玩意。

那么前置需要了解一个对象生成的过程:

我将对象的创建过程总结为:

检查常量池是否存在该对象的符号引用并确定是否经过类加载过程,都没有则进行类加载过程。

为新生对象分配内存(两种方式:指针碰撞和空闲列表<指针碰撞涉及到当指针调动频繁时为了避免出现脏读,采取本地线程分配缓冲TLAB的优先分配情况>)并将除对象头外的其他内存空间赋值W为0。

设置对象头。

对象的初始化,这个就是执行你的构造方法的过程,给你需要的字段赋值你想要定义的值。

补充一下其中的细节:为新生对象分配内存过程中,首先一个对象在类加载完成后它所需要的内存大小是完全确定的,分配内存的过程实际上就是在java堆里划分一块等大的内存给它,但是该怎么划分呢?如果java堆的内存布局是严格的顺序分配,即一边是使用过的,一边是空闲的,那么就会采取指针碰撞的方式分配内存,所谓的指针在空闲区与使用区的分界线处,收到内存需求时,指针向后移动直到移动所覆盖的长度等于java对象所需要的内存大小时停止并进行分配。但如果java堆的内存布局是碎片化的不连续的呢?我们就只能维护一个列表,这个列表记录了所有java堆空闲区的大小与位置信息,分配时只需要查找最适合新生对象的区域分配即可。

注意:java堆是否规整是由垃圾收集器的能力决定的,是否带有空间压缩整理的能力。当我们采用的收集器是Serial与Parnew时是用指针碰撞的方式分配的,当采用的是CMS垃圾收集器的时候,则是需要使用麻烦的空闲区表分配。

这里我们着重的去关注属性与方法的填充即可:一个对象的灵魂就是它的属性与方法:

整个工具用到的核心属性:

    private static volatile Constructor<?> constructor;
    private static volatile Object newInstance;
    private static volatile Map<String, Method> methodMap;

我们先看看这几个方法的作用:

  public static Constructor<?> getConstructor(Object dataType) {
        Class<?> typeClass = dataType.getClass();
        try {
            Constructor<?> constructor = typeClass.getConstructor();
            constructor.setAccessible(true);
            return constructor;
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            return null;
        }
    }

获取类型的构造器,注意这可是无参构造,如果你没有无参构造那么很有可能报错,因为我们也不知道它有多少属性对吧?(时刻记住咱们是逆向!!!不知道这个类型里有什么!!!一切都是反射带来的信息)

public static void fillValueToNewInstance(Object dataType, Map<String, Object> initialMap) throws Exception {
        constructor = getConstructor(dataType);
        Class<?> typeClass = dataType.getClass();
        Field[] declaredFields = typeClass.getDeclaredFields();
        Iterator<Field> fieldIterator = Arrays.stream(declaredFields).iterator();
        newInstance = constructor.newInstance();
        while (fieldIterator.hasNext()) {
            Field field = fieldIterator.next();
            field.setAccessible(true);
            if (initialMap != null)
                field.set(newInstance, initialMap.get(field.getName()));
        }
    }

获取属性并填充属性值,这里也顺带着将属性给进去了。

 public static Method[] getMethodArray(Object dataType) {
        return dataType.getClass().getDeclaredMethods();
    }

获取一切方法组成方法数组

  public static void fillMethodMap(Object dataType) {
        methodMap = new HashMap<>();
        Method[] methodArray = getMethodArray(dataType);
        Iterator<Method> iterator = Arrays.stream(methodArray).iterator();
        while (iterator.hasNext()) {
            Method method = iterator.next();
            method.setAccessible(true);
            methodMap.put(method.getName(), method);
        }
    }

将方法存到方法集合中去存储。

 public static Object useMethod(String methodName, @Nullable Object... parameters) throws Exception {
        return methodMap.get(methodName).invoke(newInstance, parameters);
    }

使用方法要通过名称。

    @SneakyThrows
    public static Object getBean(Object dataType, Map<String, Object> parameterMap) {
        fillValueToNewInstance(dataType, parameterMap);
        fillMethodMap(dataType);
        return newInstance;
    }

getBean方法。

  public static void main(String[] args) throws Exception {
        Map<String,Object> map = new HashMap<>();
        map.put("name","xu");
        map.put("age",Integer.valueOf(18));
        map.put("sex",'女');
        Person bean = (Person) getBean(new Person(), map);
        System.out.println(bean.toString());
        System.out.println(useMethod("toString"));
    }

测试方法。类型信息如下:

class Person {
    private String name;
    private Integer age;
    private Character sex;
    //无参构造绝对不能少
    public Person() {
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                '}';
    }
}

测试结果如下:

这里我们可没有用Person person = new Person();的方式实例化对象,用反射实现了对象的实例化。

里面用到关于反射的方法我列下来:

getDeclaredFields 获取域属性对象

getName 获取属性名称

getType 获取属性类型的字节码文件

setAccessible(true) 设置暴力破解,获取对私有属性的使用

getDeclaredMethods 获取全部方法数组

getClass 获取字节码文件

getConstructor 获取无参构造器

到此这篇关于SpringBoot实现使用反射模拟IOC和getBean的文章就介绍到这了,更多相关SpringBoot反射模拟IOC与getBean内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: SpringBoot实现使用反射模拟IOC和getBean

本文链接: https://www.lsjlt.com/news/202919.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • SpringBoot实现使用反射模拟IOC和getBean
    IOC就是spring的核心思想之一:控制反转。这里不再赘述,看我的文章即可了解: spring基础思想IOC 其次就是java的反射,反射机制是spring的重要实现核心,今天我看...
    99+
    2023-05-14
    SpringBoot反射模拟IOC SpringBoot反射模拟getBean
  • SpringBoot如何实现使用反射模拟IOC和getBean
    这篇文章主要介绍“SpringBoot如何实现使用反射模拟IOC和getBean”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“SpringBoot如何实现使用反射模拟IOC和getBean”文章能帮...
    99+
    2023-07-05
  • 使用Java反射模拟实现Spring的IoC容器的操作
    目录实现的功能:项目结构下面是程序的项目结构图:自定义注解容器实现测试实体类User的定义:实现的功能: 默认情况下将扫描整个项目的文件 可以使用@Componen...
    99+
    2024-04-02
  • springboot使用AOP+反射实现Excel数据的读取
    如果我们遇到把excel表格中的数据导入到数据库,首先我们要做的是:将excel中的数据先读取出来。因此,今天就给大家分享一个读取Excel表格数据的代码示例: 为了演示方便,首先我...
    99+
    2024-04-02
  • 使用Spring.Net如何实现控制反转IoC
    今天就跟大家聊聊有关使用Spring.Net如何实现控制反转IoC,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Spring.Net包括控制反转(IoC) 和面向切面(AOP)一、首...
    99+
    2023-05-31
    spring.net ioc
  • springboot如何使用AOP+反射实现Excel数据的读取
    这篇文章将为大家详细讲解有关springboot如何使用AOP+反射实现Excel数据的读取,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。如果我们遇到把excel表格中的数据导入到数据库,首...
    99+
    2023-06-29
  • golang 如何使用反射实现动态代理模式
    go中使用反射实现动态代理答案: 是的,可以通过反射在go中实现动态代理模式。步骤:创建自定义代理类型,包含目标对象引用和方法处理逻辑。为代理类型创建代理方法,在调用目标方法前或后执行额...
    99+
    2024-05-01
    golang 反射 动态代理
  • c++中vector的使用和模拟实现
    一、接口介绍 1、插入数据 void push_back(const T& x) 在当前vector尾部插入x,如果容量不够扩大二倍。 iterator insert(it...
    99+
    2024-04-02
  • Java 中反射的概念、作用和特点,在什么情况下使用反射及使用实例
    反射的概念 反射(Reflection)是 Java 的一种特性,它可以让程序在运行时获取自身的信息,并且动态地操作类或对象的属性、方法和构造器等。通过反射功能,可以让我们在不知道具体类名的情况下,依...
    99+
    2023-10-22
    java
  • C#使用反射机制实现延迟绑定
    反射允许我们在编译期或运行时获取程序集的元数据,通过反射可以做到: ● 创建类型的实例● 触发方法● 获取属性、字段信息● 延迟绑定...... 如果在编译期使用反射,可通过如下2种...
    99+
    2022-11-13
    C# 反射机制 延迟绑定
  • 如何使用Java注解和反射实现Junit4中的用例调用
    这篇文章主要讲解了“如何使用Java注解和反射实现Junit4中的用例调用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何使用Java注解和反射实现Junit4中的用例调用”吧!实例需求需...
    99+
    2023-06-15
  • SpringBoot利用切面注解及反射实现事件监听功能
    目录前言效果图监听原理核心源码源码地址前言 当某个事件需要被监听的时候,我们需要去做其他的事前,最简单的方式就是将自己的业务 方法追加到该事件之后。 但是当有N多个这样的需求的时候我...
    99+
    2024-04-02
  • C#使用dynamic一行代码实现反射操作
    目录C#用dynamic一行代码实现反射操作dynamic简介dynamic简化反射实现dynamic与反射的性能对比结语C#用dynamic一行代码实现反射操作 dynamic简介...
    99+
    2023-05-17
    C# dynamic反射 C#使用dynamic
  • 如何用Java注解和反射实现依赖注入
    目录概述定义注解为被注入的方法添加注解通过反射处理注解概述 在Spring中,我们可以通过 @Autowired注解的方式为一个方法中注入参数,那么这种方法背后到底发生了什么呢,这篇...
    99+
    2024-04-02
  • 如何使用Python和Matla实现模拟退火法
    这篇文章主要为大家展示了“如何使用Python和Matla实现模拟退火法”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何使用Python和Matla实现模拟退火法”这篇文章吧。1 Python...
    99+
    2023-06-29
  • Java使用反射和动态代理实现一个View注解绑定库
    目录支持的功能代码注解类实现类使用使用反射结合动态代理实现一个View注解绑定库,支持View和事件绑定,代码简洁,使用简单,扩展性强。 支持的功能 @ContentView 绑定l...
    99+
    2024-04-02
  • 怎么使用div模拟实现textarea
    这篇文章主要介绍了怎么使用div模拟实现textarea的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么使用div模拟实现textarea文章都会有所收获,下面我们一起来看看...
    99+
    2024-04-02
  • C++  STL _ Vector使用及模拟实现
    目录1.Vector的介绍1.1 Vector的介绍2.Vector的使用2.1 vector的定义2.2 vector 迭代器的使用 2.3 vector的空间增长问题3...
    99+
    2024-04-02
  • 怎么在java中利用反射实现获取和调用功能
    怎么在java中利用反射实现获取和调用功能?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Class类中获取方法:public Method[] getMetho...
    99+
    2023-05-30
    java
  • Golang函数的反射和类型断言的应用和底层实现
    Golang函数的反射和类型断言的应用和底层实现在Golang编程中,函数的反射和类型断言是两个非常重要的概念。函数的反射可以让我们在运行时动态的调用函数,而类型断言则可以帮助我们在处理接口类型时进行类型转换操作。本文将深入讨论这两个概念的...
    99+
    2023-05-16
    反射 Golang函数 类型断言
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作