手写模拟Spring的底层原理2.1

2023-10-27

先来引入两个问题

第一个懒加载还是立即加载的问题,这个问题还是在于就是说,当我们xml配置了一个对象bean的时候,它在spring容器里面是什么时候开始会给我们创建这个对象

那如果我们想对某个对象启动懒加载,可以添加@lazy这个注解

 这个注解一加上,它就只会在得到对象的时候给我们在容器中创建对象

也就是在使用下面的方法的时候才会去创建一个对象

那么默认这个对象得到的是单例还是多例,我们先来说一个小知识点

那么我们测试一下多例还是单例

 

很明显上面是单例设计模式

那么我们如何把它变成多例,就得靠下面这个注解来做

 

 java的三个类加载器分别是什么

 

 下面说关于注解的一些反射方法的用法

1.要判断在一个类上面有没有某个注解接口

configClass.isAnnotationPresent(ComponentScan.class)

利用这个类的字节码对象去调用上面的方法,内部传入我们需要去判断注解接口的字节码对象

2.如果有这个注解,我们需要去拿到这个注解对象

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

还是利用当前类字节码对象去调用getAnnotation()方法,内部传入一个我们需要得到的这个注解对象的字节码对象

3.当拿到这个注解对象之后,我们现在想要去拿到值,也就是调用内部的方法就可以了,比如value的值,直接调用value()方法

String path = componentScanAnnotation.value();

这样就可以得到配置在这个注解上面的值,重点还是value属性的值

下面讲解一下关于class文件资源路径获取的问题

 我们一般在程序的开发当中,生成的class文件会直接放到下面这个目录里面,然后我一般通过内存操作判定就是这个文件的信息

上面两者包都是对应的,只是说在target里面,他还有前面两个固定的包

 那么我们如果想获取target里面的User怎么获取

上面就是拿到类加载器,然后去调用getResource(),里面传入一个你需要查找类的相对包的路径,然后会给我们返回一个URL ,这个URL就是一个在target上面的绝对路径,他包括了整个硬盘的位置

也就是说类加载器会给我们自动凭借好target/classses这两个目录

然后通过URL的resource对象调用getFile(),就可以把这个路径变成一个字符串,然后可以传入到一个FIle对象里面,然后利用File对象我们就可以做一些事儿

 下面说一下文件对象里面的listFiles()的用法

 

 比如我刚噶上面的操作,贴过来

 

他就可以找到这个class文件的完整路径

我们还可以做一些截取操作直接拿到com\pxx\domain\User这部分

循环遍历就可以拿到domain下面的所有class文件

下面写一个简单一点的spring的源码

 这个就是先跑通最基础的程序吧,就是我们可以通过getBean去得到一个单例或者多例的对象

先把项目结构简单的弄出来

下面做一个简单的分析,怎么着手

首先我们在spring容器中我们需要一个容器对象,就类似于下面这个容器对象

所以我们把这个容器对象在我们的spring里面给创建出来,我们这里叫PxxApplicationContext对象

 下面我们要干嘛,是不是要去扫描包,为什么说我们要去扫描包,因为我们主要是扫描上面的注解

比如我们要去判断这个类上面有没有component这个注解啊,有的话,我们就要去创建这个对象

还有比如说这个对象上面有没有scope这个注解,这个注解里面给我们配置的值是单例还是多例

这些注解都要被扫描到

因为现在我们要去扫描到这些注解嘛,所以,我们先去写几个常用的注解在上面

这些注解先都是放到spring下面的annotation的包下面

第一个注解:Component注册对象用的

第二个注解: ComponentScan配置要扫描哪一个包用的

 第三个注解:Scope注解这个对象的生成是单例还是多例

好了,现就写上面三个注解

下面我们去扫描包,扫描类,扫描注解,还是去完成scan方法

大概步骤如下

写到下面我发现需要一个BeanDefinition对象来保存一些对象的信息

比如它是什么类型的Class,它的Scope是什么值,他是否采用延迟加载

于是我们去构建一个这样的对象,放到了spring下面的domain包里面

package com.spring.domian;

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 isLazy() {
        return isLazy;
    }

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

 既然有了这个我们就可以继续去改写我们的代码

写到下面这个位置,我又开始迷茫了

 于是我做了集合对象保存他们

做好了这个映射关系的集合之后,scan这个方法方法就做完了,下面贴一下代码,这个代码有详细的注释,可以结合着前面来看

package com.spring;

import com.spring.annotation.Component;
import com.spring.annotation.ComponentScan;
import com.spring.annotation.Scope;
import com.spring.domian.BeanDefinition;

import java.io.File;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
 * @author pxx
 */
public class PxxApplicationContext {

    //内部需要传入一个配置类的class字节码文件
    private Class configClass;
    //这个集合用来存放对象与它的BeanDefinitionMap的映射信息
    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();

    //写一个构造函数
    //这个构造函数不止是帮我们传入这个配置类的calss对象
    //还要帮我们做一些初始化操作,比如如果一个对象是单例
    //这个ApplicationContext new出来之后,就会创建这个对象

    public PxxApplicationContext(Class configClass) {
        this.configClass = configClass;

        //写一个函数做一些扫描的动作
        scan(configClass);//从这个配置类上面的包开始进行解析

    }

    //下面我们定义scan这个扫描的方法
    private void scan(Class configClass) {
        //先来判断有没有ComponentScan这个注解
        if(configClass.isAnnotationPresent(ComponentScan.class)) {
            //如果上面这个配置类有需要扫描的包的注解
            //那么我们就要取出里面的值=》然后去扫描相应的包
            //既然有了,那么我们就拿到这个ComponentScan这个对象
            ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
            String path = componentScanAnnotation.value();//就能得到我们需要扫描的包
            path = path.replace(".","/");//因为得到的是com.pxx.service
            //但是我们下面要去利用文件扫描,我们需要一个真实的路径,所以上面需要替换一下

            //上面就得到了我们需要扫描的包
            //那么我们真正要扫描的是什么?是源代码文件吗?并不是,我们需要的是一个class字节码对象文件
            //我们真正要去扫的是这个class文件,这个文件很多对象的信息嘛
            //怎么得到这个文件位置,我们用类加载器器来做
            //类加载器一般就用来寻找资源文件
            ClassLoader classLoader = PxxApplicationContext.class.getClassLoader();
            //这里你可以这样,他会自动去开始从target/classes下面开始拼接你这个额path路径
            URL resource = classLoader.getResource(path);//这个就会绝对的路径URl对象,是在target里面
            //把这个路径变成字符串然后封装到File对象,我们用Filed对象再去遍历这个文件夹下面的每一个类
            File file = new File(resource.getFile());

            //下面开始遍历这个绝对路径下面的文件
            if (file.isDirectory()) {
                for (File f : file.listFiles()) {
                    //我们要去拿到的是什么
                    //其实就是com.pxx.servcie下面的每一个类的全限定类名
                    //比如com.pxx.service.User com.pxx.service.Order ..
                    String absolutePath = f.getAbsolutePath();
                    //主要在于这里我们需要按照字符串位置截取
                    //这里会截出一个com\pxx\service\User  比如com\pxx\service\Ortder
                    absolutePath = absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));
                    //我们把上面的\全部变成.,因为后面我们需要加载进内存
                    absolutePath = absolutePath.replace("\\",".");

                    //上面基本的找类的字节码对象就已经找到了
                    //下面我们就需要把这些类加载到内存里面,然后变成一个Class字节码对象
                    //因为只有变成Class字节码对象,我们才能去查找这个类上面有什么注解
                    try {
                        Class<?> clazz = classLoader.loadClass(absolutePath);
                        //判断这个字节码对象有没有Component注解
                        if(clazz.isAnnotationPresent(Component.class)) {
                            //如果有这个注解,说明这个对象需要被getBean创建
                            //我们拿到一个注解的名字,在Component里面,可能配了名字,可能没有
                            Component componentAnno = clazz.getAnnotation(Component.class);
                            String beanName = componentAnno.value();
                            //结合下面来看每一个对象好像都有一些信息配置
                            //那么我们就考虑到为了灵活性
                            //我们就把这些信息封装到一个BeanDefinition对象里面
                            BeanDefinition beanDefinition = new BeanDefinition();
                            //设置一下它的class类型
                            beanDefinition.setType(clazz);//什么类的字节码对象
                            //然后我们又要去判断有没有Scope这个注解
                            if(clazz.isAnnotationPresent(Scope.class)) {
                                //如果有这个注解,我们就要去得到这个注解的对象
                                Scope scopeAnn = clazz.getAnnotation(Scope.class);//从内存中就得到了这个注解对象
                                String value = scopeAnn.value();//用来判断这里是单例还是多例
                                //这里还是把信息封装到BeanDefinition里面
                                beanDefinition.setScope(value);
                            } else {
                                //如果没有这个注解说明它就是一个单例
                                beanDefinition.setScope("singleton");//这是这个Scope注解的可用取值
                            }

                            //写到这,我们又得来考虑一个问题
                            //首先就是说在com.pxx.service下面他不止一个class,有很多
                            //那么也就是说产生的BeanDefinition就会有很多,就是会有很多对象的信息的嘛
                            //那么我们这里为了区分,我们指定用beanName->BeanDefinition对象
                            //上面有一个映射关系,那么我们就做一个集合存进去
                            beanDefinitionMap.put(beanName,beanDefinition);
                        }
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

}

下面我们测一下,写几个类,看看这个map里面有没有把对象收录进去

下面在service包里面做了两个service对象

 

下面这个service是一个什么都没有加的service

 

然后我们要去写一个配置类用于开启包扫描

 

然后写我们主方法,写之前我在scan里面打印了一下保存对象信息的map集合

 然后主方法直接new,上面的构造方法开始运行

看一下运行结果

 

打印了两个对象,完美,因为有一个对象没有加任何注解,所以下面 他根本进不去

找到Class字节码对象之后,验证了有Component注解才会进去

还有一个小问题是,我刚刚没在@Component注解里面写名字,所有对象进来都没有名字,去测试一下发现确实为空

 

我们先去给注解加上名字,方便后面进行测试

 

 下面再去测名字就进去了

 下面我们就要去写getBean方法来给我们生产对象

写到这个位置,我又卡住了单例多例这里怎么来设计

单例必须保证每次取出来的对象都是同一个对象,我考虑用一个集合来做,如果同一个对象过来,都从集合里面取出唯一的键,然后获取固定的对象不就好了

因此我在做一个下面的映射集合存放名字与对象的映射集合

 

 上面除了createBean这个方法没有之外,还是存在一个问题的,也就是,单例从集合中取,第一次过来数据从哪里来的?

这个时候,我们考虑一个问题,那就是spirng的加载模式,是在new 一个容器之后就创建出来对象,还是getBean时创建出来对象吗,这里我们默认是立即加载

既然这样,那么我们创建对象的工作,就必须放到容器的构造函数里面执行,也就是说,san包扫描完成之后,把相应的对象信息都放到集合里面去了之后,就要卡死给我们生产对象

于是我们去修改代码

先来看一个方法

这个是HashMap里面的饿方法,把集合里面元素放到Set集合里面,Set集合内部保存的是一个Entry对象,有 下面两个方法

好了继续我们的代码,说这个只是因为等会我要用增强for循环来遍历beanDefinitionMap里面的数据

再来说一点

 这个位置加载不同类的class文件,会返回不同类Class类的信息。

所以这里放进来的也不是不同类的Class字节码对象

下面直接上完整代码

package com.spring;

import com.spring.annotation.Component;
import com.spring.annotation.ComponentScan;
import com.spring.annotation.Scope;
import com.spring.domian.BeanDefinition;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
 * @author pxx
 */
public class PxxApplicationContext {

    //内部需要传入一个配置类的class字节码文件
    private Class configClass;
    //这个集合用来存放对象与它的BeanDefinitionMap的映射信息
    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
    //这个用来存放bean名字与之对应的对象
    private Map<String, Object> singletonObjects = new HashMap<>();

    //写一个构造函数
    //这个构造函数不止是帮我们传入这个配置类的calss对象
    //还要帮我们做一些初始化操作,比如如果一个对象是单例
    //这个ApplicationContext new出来之后,就会创建这个对象

    public PxxApplicationContext(Class configClass) {
        this.configClass = configClass;

        //写一个函数做一些扫描的动作
        scan(configClass);//从这个配置类上面的包开始进行解析

        //立即加载,new一个对象之后马上创建Bean对象
        //采用循环,遍历出beanDefinitionMap里面能的beanName
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            String beanName = entry.getKey();//得到bean的名字
            BeanDefinition beanDefinition = entry.getValue();//得到对应的对象信息
            //这里不管是单例都应该马上创建一个对象出来
            Object bean = createBean(beanName, beanDefinition);
            //再来判断一把,如果这个对象是单例,放到集合里面去
            if (beanDefinition.getScope().equals("singleton")) {
                singletonObjects.put(beanName,bean);
            }
        }

    }

    //下面我们定义scan这个扫描的方法
    private void scan(Class configClass) {
        //先来判断有没有ComponentScan这个注解
        if(configClass.isAnnotationPresent(ComponentScan.class)) {
            //如果上面这个配置类有需要扫描的包的注解
            //那么我们就要取出里面的值=》然后去扫描相应的包
            //既然有了,那么我们就拿到这个ComponentScan这个对象
            ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
            String path = componentScanAnnotation.value();//就能得到我们需要扫描的包
            path = path.replace(".","/");//因为得到的是com.pxx.service
            //但是我们下面要去利用文件扫描,我们需要一个真实的路径,所以上面需要替换一下

            //上面就得到了我们需要扫描的包
            //那么我们真正要扫描的是什么?是源代码文件吗?并不是,我们需要的是一个class字节码对象文件
            //我们真正要去扫的是这个class文件,这个文件很多对象的信息嘛
            //怎么得到这个文件位置,我们用类加载器器来做
            //类加载器一般就用来寻找资源文件
            ClassLoader classLoader = PxxApplicationContext.class.getClassLoader();
            //这里你可以这样,他会自动去开始从target/classes下面开始拼接你这个额path路径
            URL resource = classLoader.getResource(path);//这个就会绝对的路径URl对象,是在target里面
            //把这个路径变成字符串然后封装到File对象,我们用Filed对象再去遍历这个文件夹下面的每一个类
            File file = new File(resource.getFile());

            //下面开始遍历这个绝对路径下面的文件
            if (file.isDirectory()) {
                for (File f : file.listFiles()) {
                    //我们要去拿到的是什么
                    //其实就是com.pxx.servcie下面的每一个类的全限定类名
                    //比如com.pxx.service.User com.pxx.service.Order ..
                    String absolutePath = f.getAbsolutePath();
                    //主要在于这里我们需要按照字符串位置截取
                    //这里会截出一个com\pxx\service\User  比如com\pxx\service\Ortder
                    absolutePath = absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));
                    //我们把上面的\全部变成.,因为后面我们需要加载进内存
                    absolutePath = absolutePath.replace("\\",".");

                    //上面基本的找类的字节码对象就已经找到了
                    //下面我们就需要把这些类加载到内存里面,然后变成一个Class字节码对象
                    //因为只有变成Class字节码对象,我们才能去查找这个类上面有什么注解
                    try {
                        Class<?> clazz = classLoader.loadClass(absolutePath);
                        //判断这个字节码对象有没有Component注解
                        if(clazz.isAnnotationPresent(Component.class)) {
                            //如果有这个注解,说明这个对象需要被getBean创建
                            //我们拿到一个注解的名字,在Component里面,可能配了名字,可能没有
                            Component componentAnno = clazz.getAnnotation(Component.class);
                            String beanName = componentAnno.value();
                            //结合下面来看每一个对象好像都有一些信息配置
                            //那么我们就考虑到为了灵活性
                            //我们就把这些信息封装到一个BeanDefinition对象里面
                            BeanDefinition beanDefinition = new BeanDefinition();
                            //设置一下它的class类型
                            beanDefinition.setType(clazz);//什么类的字节码对象
                            //然后我们又要去判断有没有Scope这个注解
                            if(clazz.isAnnotationPresent(Scope.class)) {
                                //如果有这个注解,我们就要去得到这个注解的对象
                                Scope scopeAnn = clazz.getAnnotation(Scope.class);//从内存中就得到了这个注解对象
                                String value = scopeAnn.value();//用来判断这里是单例还是多例
                                //这里还是把信息封装到BeanDefinition里面
                                beanDefinition.setScope(value);
                            } else {
                                //如果没有这个注解说明它就是一个单例
                                beanDefinition.setScope("singleton");//这是这个Scope注解的可用取值
                            }

                            //写到这,我们又得来考虑一个问题
                            //首先就是说在com.pxx.service下面他不止一个class,有很多
                            //那么也就是说产生的BeanDefinition就会有很多,就是会有很多对象的信息的嘛
                            //那么我们这里为了区分,我们指定用beanName->BeanDefinition对象
                            //上面有一个映射关系,那么我们就做一个集合存进去
                            beanDefinitionMap.put(beanName,beanDefinition);
                        }
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    //下面我们去实现一个创建对象的方法
    private Object createBean(String beanName, BeanDefinition beanDefinition) {
        //这里先简单写一些,等会方便测试
        Class clazz = beanDefinition.getType();//它是哪一个类的对象实例,之前scan就已经扫进去了
        Object instance = null;
        try {
            instance = clazz.getConstructor().newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return instance;

    }


    public Object getBean(String beanName) {
        //先从map集合中去看有没有名字与之对应的BeanDefinition信息
        if (!beanDefinitionMap.containsKey(beanName)) {
            throw new NullPointerException();
        }

        //如果有,我们从beanDefinitionMap中取出这个相应对象的信息
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);

        //然后根据内部属性判断这个对象是单例还是多例
        if (beanDefinition.getScope().equals("singleton")) {
            //单例设计
            Object singleBean = singletonObjects.get(beanName);
            return singleBean;
        } else {
            //多例
            //多例,其实就是每次都要重新创建一个对象
            Object prototypeBean = createBean(beanName, beanDefinition);
            return prototypeBean;
        }
    }



}

测试

下面改成多例测试一下

 

 

明显一测试就不一样了

下面说一下@Scope这里设置值的问题 

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

手写模拟Spring的底层原理2.1 的相关文章

  • 在 th:href 链接中使用模型属性

    有没有办法在 th href 链接中引用模型属性 例如 a a Here 当前用户是控制器中指定的模型变量 这可以很容易地访问 如th text标签 但是 那th href百里香解析失败 如果有任何方法以这种方式引用模型属性 则在th hr
  • 如何在 Spring Boot 1.4 中自定义 Jackson

    我一直无法找到如何使用的示例Jackson2ObjectMapperBuilderCustomizer java在spring boot 1 4中自定义Jackson的功能 boot 1 4 中自定义 Jackson 的 doco http
  • 将对象列表传递给 Freemarker 然后循环

    我已经熟悉了 FreeMarker 一个 Java 模板引擎 我已经能够通过哈希映射将对象传递给模板引擎了 这样就可以了 但是 一旦我尝试将任何类型的多个对象集传递给 FreeMarker 它就会给我一个 freemarker templa
  • 使用Optional作为类中的属性是一个好习惯吗? [复制]

    这个问题在这里已经有答案了 我读过一些关于目的的内容Optional 不幸的是我不记得在哪里 在Java 8中 我很惊讶作者没有提到使用Optional作为类中的属性 由于我在课堂上经常使用选项 我想知道这是否是一个好的做法 或者我可以更好
  • Android 背景 + 文本 + 按钮图标

    我想要一个图像设置为文本的背景 并在文本的左侧设置一个图标 在iPhone中非常简单 但不知道如何在Android上做到这一点 调整按钮的大小并保持图标 文本的位置和距离正确 iPhone 安卓我有这个 xml代码是
  • com.google.gwt.dev.jjs.InternalCompilerException:访问期间出现意外错误

    我在使用版本 2 6 0 编译 gwt 应用程序时遇到以下错误 最初我用 gwt 版本 2 6 1 的 maven 编译它 然后尝试通过版本 2 6 0 的 eclipse 编译它 跟版本兼容有关系吗 com google gwt dev
  • 全屏独占模式下的 AWT 框架在窗口弹出对话框中最小化

    我正在开发一个在全屏独占模式下使用 awt 框架的应用程序 一切正常 直到弹出窗口可见 这会抢走焦点 我的应用程序将被最小化 这是我的框架的初始化代码 if ApplicationConfig getInstance useFullscre
  • 在 Eclipse 中导航 Java 调用堆栈

    在调试器中像GDB http sources redhat com gdb 当您在断点处停止时 您可以轻松地向上移动调用堆栈并检查相关的源和堆栈帧数据 在 Eclipse 中如何做到这一点 In the 调试视角 http www ibm
  • Spring @Transactional 并发

    class MyService 公共无效a 同步 某个键 b Transactional 传播 传播 REQUIRES NEW 公共无效b 数据库工作吗 除非您使用代码编织 否则这是行不通的 Spring处理事务的默认方式是通过AOP代理
  • Apache POI 的 ProGuard 设置

    我正在构建一个使用 Apache POI 库的应用程序 当我调试应用程序 在不运行 Proguard 的情况下编译它 时 一切都运行良好 但是在导出 APK 后 当我运行应用程序并打开 Excel 文件时 出现以下异常 RuntimeExc
  • 使用 viewModel 从 ChildFragment 访问 ParentFragment 中的 ViewModel

    我正在尝试访问ParentViewModel for ParentFragment from ChildFragment using viewModels 这是我的代码 In ParentFragment class ParentFragm
  • 用 Java 捕获扬声器输出

    使用Java可以捕获扬声器输出吗 此输出不是由我的程序生成的 而是由其他正在运行的应用程序生成的 这可以用 Java 完成还是我需要求助于 C C 我有一个基于 Java 的应用程序 使用过的爪哇声音 https stackoverflow
  • 摆动刷新周期

    我试图了解何时使用重新验证 重绘 打包 令人惊讶的是 我没有找到详细的底层文档 请随意链接 到目前为止我已经明白这都是 RepaintManager 的责任 油漆 重新油漆指的是脏 干净的东西 pack validate revalidat
  • 根据结果​​重试方法(而不是异常)

    我有一个具有以下签名的方法 public Optional
  • Java可以进行进程监控吗?

    是否可以用Java编写一个在托盘中运行的应用程序 并且当启动某个应用程序时 它可以检测到它 我想对某些程序执行此操作 以了解我每周使用它们多长时间 我是 Java 新手 所以我不知道 Java 是否是最适合此操作的语言 或者它是否具有对操作
  • Jersey bean 验证 ParameterNameProvider

    我正在阅读关于泽西岛的文档Bean验证 https jersey java net documentation latest bean validation html The ParameterNameProvider示例显示如何定义方法的
  • Hive NVL 不适用于列的日期类型 - NullpointerException

    我正在使用 HDFS 上的 MapR Hive 发行版并面临以下问题 如果表的列类型是 日期 类型 则NVL https cwiki apache org confluence display Hive LanguageManual UDF
  • 如果可能,将 jFrame 输出到第二台显示器

    我在 Java 中的 Swing 上有一个 jFrame 我希望它输出到第二个监视器 如果该监视器存在 我尝试过这个 通过this http download oracle com javase 6 docs api java awt Gr
  • Selenium Webdriver 中的 IF 语句

    我想知道是否有人可以帮助我解决我正在尝试解决的问题以及 Java 中 Webdriver 的 If 语句 当登录到我正在测试的应用程序时 可以在主页之前进入安全问题页面 如果是新用户等 我希望测试中的代码做的是 如果出现安全问题页面 请填写
  • Ant 类路径和 junit.jar

    我有一个 build xml 它允许我运行 junit 测试 这是相关部分

随机推荐

  • 嵌入式学习——c语言数据的输入输出

    嵌入式学习 c语言数据的输入输出 一 输入输出概念 1 2C语言本身不提供输入输出语句 1 3 include头文件放在程序中 二 printf输出数据 2 2格式字符 三 scanf输入数据 3 1scanf一般格式 四 输入输出函数 4
  • Spring Boot之分离测试和生产环境的应用配置

    多环境应用配置 将默认不变的配置 设置在application properties文件中 新建开发环境下的属性文件application dev properties 将开发中的配置 设置在该文件中 新建生产环境下的属性文件applica
  • “点两下”就能开发一个AI应用!百度砸亿元基金、千万算力要搞插件生态

    金磊 发自 武汉量子位 公众号 QbitAI 这年头 要想开发一个AI应用 怎么搞 只需要简单的 点击 动作就可以了 例如你想开发一个AI作画的App 只需要先点击与之相匹配的能力 简笔成画 根据手绘草图和语言 生成符合要求的图片 言语之美
  • fiddler设置好代理后不能上网(方法二)

    1 打开fiddler在工具栏找到Tools gt options Connections选项如下图 将Allow remote computers to connect 勾选上 然后记住默认8888这个端口 可更改 设置手机代理时会用到
  • 2023高教社数学建模国赛A题 - 定日镜场的优化设计 - 思路

    问题1 计算年平均光学效率和输出热功率 建立模型的坐标系 以圆形区域中心为原点 正东方向为x轴 正北方向为y轴 垂直地面向上为z轴 计算吸收塔和定日镜的位置 吸收塔建于圆形定日镜场中心 根据给定的数据确定定日镜的位置 计算每个定日镜的光学效
  • 使用阿里云OSS实现文件的上传、下载、删除及修改功能

    一 配置OSS相关配置信息 1 要配置 OSS 相关配置信息 您可以按照以下步骤操作 登录阿里云控制台 进入 OSS 控制台 创建一个新的 OSS Bucket 并记录下以下信息 Bucket 名称 Bucket 所属地域 AccessKe
  • 如何解决git上传文件出错[rejected] master -> master (fetch first) error: failed to push some refs to '

    rejected master gt master fetch first error failed to push some refs to git gitee co 上传到码云的时候 报了这个错误 rejected master gt
  • 使用sklearn学习多项式回归(三)

    目录 1 什么是线性 1 1 变量之间的线性关系 1 2 数据间的线性与非线性 1 3 线性模型与非线性模型 1 4 使用分箱处理非线性问题 2 多项式回归PolynomialFeatures 2 1 什么是多项式回归 2 2 多项式回归处
  • 使用 Openssl 验证自签名证书

    原文地址 http blog csdn net kmyhy article details 6546072 iOS的 security framework 框架前面已经介绍 这个框架提供有限的功能 使用它能做到的 比你想象的要少 笔者一直想
  • html input 禁用缓存

    多数浏览器默认会缓存input的值 只有使用ctl F5强制刷新的才可以清除缓存记录 如果不想让浏览器缓存input的值 有2种方法 input 的属性autocomplete 默认为on 其含义代表是否让浏览器自动记录之前输入的值 很多时
  • word编辑公式简单方法

    安装Python包 pix2tex 在终端输入 pip install pix2tex gui i https pypi doubanio com simple 就可以安装 安装好以后 在终端输入pix2tex gui就可以启动 第一次启动
  • Android多级树形选择列表案例 - 手把手教你快速实现

    公司项目中有一个选择联系人的界面 一看里面关系极其复杂 最多时有5层关系嵌套 层数还不一定 有的是第五级是人员 有的是第四级是人员 崩溃中 原来的实现方式是分了三个Activity去分别加载 个人觉得太过臃肿麻烦 选个人要调四次页面 太繁琐
  • Vite原理学习之预编译

    前言 Vite是下一代的前端开发与构建工具 为什么称为下一代 根本原因在于其基于原生ES Module 在目前的前端工程化生态中 webpack rollup esbuild等非常流行 而Vite真是构建在一些流行的技术上 Vite的出现实
  • mysql按升序创建索引_MySQL中如何使用索引

    原标题 MySQL中如何使用索引 者 Airy 在数据分析之路狂奔 立志成为大咖级人物 前言 学完基础的MySQL知识 以及MySQL的增删改查 我们要学习一些性能方面的东西 今天来讲一下索引 Index 索引 在关系数据库中 索引是一种单
  • BUUCTF学习笔记-EasySQL

    BUUCTF学习笔记 EasySQL 时间 2020 03 14 考点 堆叠注入 SQL模式 打开是一个输入框 提交参数查询 随意提交几个参数 发现存在堆叠注入 输入1显示Array 0 gt 1 输入2显示Array 0 gt 1 输入2
  • SQL基础之增、删、改、查

    文章目录 SQL基础之增 删 改 查 SELECT INSERT UPDATE DELETE 参考 SQL基础之增 删 改 查 SQL Structured Query Language SELECT 查 SELECT FROM 整张表查询
  • ACwing算法基础课全程笔记(2021年8月12日开始重写+优化)

    更好的阅读体验 基础模板 2021年8月12日开始对基础课笔记进行重写 优化 请大家支持AcWing正版 购买网课能让自己获得更好的学习体验哦 链接 https www acwing com about 比赛常用技巧及库函数 1 快速读 快
  • win11 install wsl2

    在 Windows 11 上安装 WSL 2 的步骤如下 首先 确保你的 Windows 版本是 Windows 11 或者更新的版本 并且支持 WSL 2 然后 打开 设置 应用 在 更新与安全 页面的 开发人员选项 中 启用 Windo
  • 用200行C语言代码写出一个贪吃蛇——1.0(基本版)

    1 设计思路 总的来说 贪吃蛇这个小游戏涉及到的东西不多 但是对逻辑思维是比较吃基本功的 贪吃蛇 显示给我们看的有三部分 蛇 食物 地图边界 我们可以用一个二维数组来标记这些部分 例如这里我创建了一个 5 10 的二维数组 其中 1 表食物
  • 手写模拟Spring的底层原理2.1

    先来引入两个问题 第一个懒加载还是立即加载的问题 这个问题还是在于就是说 当我们xml配置了一个对象bean的时候 它在spring容器里面是什么时候开始会给我们创建这个对象 那如果我们想对某个对象启动懒加载 可以添加 lazy这个注解 这