手写Spring底层原理

news2024/11/25 11:55:17

一.创建maven项目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二.创建对应的文件夹,分别是spring和nickel

在这里插入图片描述
说明:spring文件夹用于存放spring相关的文件,nickel用于存放相应的配置文件和相关被spring加载的bean对象。

三.创建对对应的文件

3.1创建CommponentScan注解文件

package com.spring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:21
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface CommponentScan {
    String value() default "";
}

在这里插入图片描述
说明:该注解用于配置文件类上,用于spring应该扫描路径

3.2创建NickelAppConfig类

package com.spring;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:55
 */
@CommponentScan("com.nickel.service")
public class NickelAppConfig {
}

在这里插入图片描述

说明:该类用于配置Spring应该扫描的文件夹,通过CommponentScan注解里面的值来确定扫描的路径

3.3创建NickelAnnotationConfigApplicationContext

package com.spring;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:20
 */
public class NickelAnnotationConfigApplicationContext {

    private Class scanConfig;

    public NickelAnnotationConfigApplicationContext(Class scanConfig){
        this.scanConfig=scanConfig;
    }

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

在这里插入图片描述

说明:该类是spring加载容器,当spring加载时候,会加载该类,通过会加载所有Commponent注解的类,同时判断是单例加载还是多例加载,还有执行初始化相关的方法

3.4创建Commponent注解

package com.spring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:21
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Commponent {
    String value() default "";
}

在这里插入图片描述
说明:注解用于扫描的类上,用于管理该类是否被spring进行管理,value值用于存放在spring加载的key值

3.5创建Scope注解

package com.spring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:36
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {
    String value() default "";
}

在这里插入图片描述
说明:Scope注解用于类上,用于说明改类是单例bean,还是多实例bean,当没有Scope注解和Scope的value值为singleton为单实例bean,当值为prototype为多实例bean

3.6创建UserService类

package com.nickel.service;

import com.spring.Commponent;
import com.spring.Scope;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:43
 */
@Commponent("userService")
@Scope("singleton")
public class UserService {

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

在这里插入图片描述

说明:改类有Commponent注解,表示会被spring加载,Scope的value值为singleton表示该类会被spring加载

3.7创建OrderService类

package com.nickel.service;


/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:44
 */
public class OrderService {
}

在这里插入图片描述
说明:该类没有Commponent注解,表示在spring加载的时候不会加载该类

四.Spring扫描的实现

4.1 在Test类中写对应的测试方法

package com.nickel;

import com.nickel.service.UserService;
import com.spring.NickelAnnotationConfigApplicationContext;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:16
 */
public class Test {
    public static void main(String[] args) {
        NickelAnnotationConfigApplicationContext context=new NickelAnnotationConfigApplicationContext(NickelAppConfig.class);
        UserService userService = (UserService)context.getBean("userService");

        userService.test();
    }
}

说明:该类目前未实现加载bean的方法,所以执行该方法会报错,实现后续的方法将会加载。

4.2 NickelAnnotationConfigApplicationContext获取扫描的路径

package com.spring;

import java.lang.annotation.Annotation;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:20
 */
public class NickelAnnotationConfigApplicationContext {

    private Class scanConfig;

    public NickelAnnotationConfigApplicationContext(Class scanConfig){
        this.scanConfig=scanConfig;

        //扫描逻辑
        if (scanConfig.isAnnotationPresent(CommponentScan.class)) {
            CommponentScan commponentScan =(CommponentScan)scanConfig.getAnnotation(CommponentScan.class);
            String path=commponentScan.value();

            System.out.println(path);
        }
    }

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

在这里插入图片描述

说明:获取扫描配置文件中,CommponentScan注解的value值,获取spring项目的扫描路径

4.3创建对象BeanDefinition

package com.spring;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 9:42
 */
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;
    }
}

说明:该类用于存储被Conponent注解标识的类。

4.3 通过SpringLoader来加载该类

package com.spring;

import java.lang.annotation.Annotation;
import java.net.URL;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:20
 */
public class NickelAnnotationConfigApplicationContext {

    private Class scanConfig;

    public NickelAnnotationConfigApplicationContext(Class scanConfig){
        this.scanConfig=scanConfig;

        //扫描逻辑
        if (scanConfig.isAnnotationPresent(CommponentScan.class)) {
            CommponentScan commponentScan =(CommponentScan)scanConfig.getAnnotation(CommponentScan.class);
            String path=commponentScan.value();
            path=path.replace(".","/");
            System.out.println(path);
            
            
            //通过ApplicationContext来加载该类
            ClassLoader classLoader = NickelAnnotationConfigApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(path);
        }
    }

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

在这里插入图片描述
说明:由于springLoader是通过相对路径来加载文件的,相对路径的文件路径为/./…这种形式,所以在加载的时候‘.’路径修改为‘/’路径。

4.4 判断该类是否有Component注解和Scope注解来走不同的逻辑

package com.spring;

import java.io.File;
import java.lang.annotation.Annotation;
import java.net.FileNameMap;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:20
 */
public class NickelAnnotationConfigApplicationContext {

    private Class scanConfig;

    public NickelAnnotationConfigApplicationContext(Class scanConfig){
        this.scanConfig=scanConfig;

        //扫描逻辑
        if (scanConfig.isAnnotationPresent(CommponentScan.class)) {
            CommponentScan commponentScan =(CommponentScan)scanConfig.getAnnotation(CommponentScan.class);
            String path=commponentScan.value();
            path=path.replace(".","/");
            
            
            //通过ApplicationContext来加载该类
            ClassLoader classLoader = NickelAnnotationConfigApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(path);

            File file=new File(resource.getPath());
            for (File listFile : file.listFiles()) {
                String absolutePath = listFile.getAbsolutePath();
                absolutePath=absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));
                absolutePath=absolutePath.replace("\\",".");
                System.out.println(absolutePath);

                try {
                    Class<?> aClass = classLoader.loadClass(absolutePath);
                    if (aClass.isAnnotationPresent(Commponent.class)) {


                        //判断该类是单例加载还是多例加载,没有Scope注解表示多例
                        if (aClass.isAnnotationPresent(Scope.class)) {
                            Scope annotation = aClass.getAnnotation(Scope.class);
                            String value = annotation.value();
                            if(value.equals("singleton")){
                                //单例
                            }else{
                                //多例
                            }
                        }else{
                            //单例
                        }
                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
    }

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

在这里插入图片描述
说明:这里获取所有具有Commponent注解的类,这个类将会被spring加载,同时具有Scope注解值value为singleton将会被加载一次,其他的将会被加载多次。

4.4 提取扫描方法,创建beanDefinition对象,并把对象存放在beanDefinitionMap

package com.spring;

import java.io.File;
import java.lang.annotation.Annotation;
import java.net.FileNameMap;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:20
 */
public class NickelAnnotationConfigApplicationContext {

    private Class scanConfig;
    private Map<String,BeanDefinition> beanDefinitionMap=new HashMap<>();

    public NickelAnnotationConfigApplicationContext(Class scanConfig){
        this.scanConfig=scanConfig;

        //扫描逻辑
        scan(scanConfig);
    }

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

    private void scan(Class scanConfig) {
        if (scanConfig.isAnnotationPresent(CommponentScan.class)) {
            CommponentScan commponentScan =(CommponentScan) scanConfig.getAnnotation(CommponentScan.class);
            String path=commponentScan.value();
            path=path.replace(".","/");


            //通过ApplicationContext来加载该类
            ClassLoader classLoader = NickelAnnotationConfigApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(path);

            File file=new File(resource.getPath());
            for (File listFile : file.listFiles()) {
                String absolutePath = listFile.getAbsolutePath();
                absolutePath=absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));
                absolutePath=absolutePath.replace("\\",".");
                System.out.println(absolutePath);

                try {
                    Class<?> aClass = classLoader.loadClass(absolutePath);
                    if (aClass.isAnnotationPresent(Commponent.class)) {
                        //获取beanName
                        Commponent commponentAnnotation = aClass.getAnnotation(Commponent.class);
                        String beanName=commponentAnnotation.value();


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

                        //判断该类是单例加载还是多例加载,没有Scope注解表示多例
                        if (aClass.isAnnotationPresent(Scope.class)) {
                            Scope annotation = aClass.getAnnotation(Scope.class);
                            String value = annotation.value();
                            beanDefinition.setScope(value);
                        }else{
                            beanDefinition.setScope("singleton");
                        }

                        beanDefinitionMap.put(beanName,beanDefinition);
                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在这里插入图片描述

4.5 创建bean方法,同时创建一个singletonObjects对象用于存所有单实例bean

package com.spring;

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

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:20
 */
public class NickelAnnotationConfigApplicationContext {

    private Class scanConfig;
    private Map<String,BeanDefinition> beanDefinitionMap=new HashMap<>();
    private Map<String,Object> singletonObjects=new HashMap<>();

    public NickelAnnotationConfigApplicationContext(Class scanConfig){
        this.scanConfig=scanConfig;

        //扫描逻辑
        scan(scanConfig);

        //创建bean
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            String beanName=entry.getKey();
            BeanDefinition beanDefinition= entry.getValue();
            if (beanDefinition.getScope().equals("singleton")) {
                   Object singletonBean=createBean(beanName,beanDefinition);
                singletonObjects.put(beanName,singletonBean);
            }
        }

    }

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

    private Object createBean(String beanName,BeanDefinition beanDefinition){
        Class clazz=beanDefinition.getType();
        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;
    }

    private void scan(Class scanConfig) {
        if (scanConfig.isAnnotationPresent(CommponentScan.class)) {
            CommponentScan commponentScan =(CommponentScan) scanConfig.getAnnotation(CommponentScan.class);
            String path=commponentScan.value();
            path=path.replace(".","/");


            //通过ApplicationContext来加载该类
            ClassLoader classLoader = NickelAnnotationConfigApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(path);

            File file=new File(resource.getPath());
            for (File listFile : file.listFiles()) {
                String absolutePath = listFile.getAbsolutePath();
                absolutePath=absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));
                absolutePath=absolutePath.replace("\\",".");
                System.out.println(absolutePath);

                try {
                    Class<?> aClass = classLoader.loadClass(absolutePath);
                    if (aClass.isAnnotationPresent(Commponent.class)) {
                        //获取beanName
                        Commponent commponentAnnotation = aClass.getAnnotation(Commponent.class);
                        String beanName=commponentAnnotation.value();


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

                        //判断该类是单例加载还是多例加载,没有Scope注解表示多例
                        if (aClass.isAnnotationPresent(Scope.class)) {
                            Scope annotation = aClass.getAnnotation(Scope.class);
                            String value = annotation.value();
                            beanDefinition.setScope(value);
                        }else{
                            beanDefinition.setScope("singleton");
                        }

                        beanDefinitionMap.put(beanName,beanDefinition);
                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在这里插入图片描述

4.6getBean方法修改

package com.spring;

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

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:20
 */
public class NickelAnnotationConfigApplicationContext {

    private Class scanConfig;
    private Map<String,BeanDefinition> beanDefinitionMap=new HashMap<>();
    private Map<String,Object> singletonObjects=new HashMap<>();

    public NickelAnnotationConfigApplicationContext(Class scanConfig){
        this.scanConfig=scanConfig;

        //扫描逻辑
        scan(scanConfig);

        //创建bean
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            String beanName=entry.getKey();
            BeanDefinition beanDefinition= entry.getValue();
            if (beanDefinition.getScope().equals("singleton")) {
                Object singletonBean=createBean(beanName,beanDefinition);
                singletonObjects.put(beanName,singletonBean);
            }
        }

    }

    public Object getBean(String beanName){
        if (!beanDefinitionMap.containsKey(beanName)) {
           throw new NullPointerException();
        }

        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if(beanDefinition.getScope().equals("singleton")){
           Object singletonBean=singletonObjects.get(beanName);
           if(singletonBean==null){
               singletonBean=createBean(beanName,beanDefinition);
               singletonObjects.put(beanName,singletonBean);
           }
           return singletonBean;
        }else{
            return createBean(beanName,beanDefinition);
        }
    }

    private Object createBean(String beanName,BeanDefinition beanDefinition){
        Class clazz=beanDefinition.getType();
        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;
    }

    private void scan(Class scanConfig) {
        if (scanConfig.isAnnotationPresent(CommponentScan.class)) {
            CommponentScan commponentScan =(CommponentScan) scanConfig.getAnnotation(CommponentScan.class);
            String path=commponentScan.value();
            path=path.replace(".","/");


            //通过ApplicationContext来加载该类
            ClassLoader classLoader = NickelAnnotationConfigApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(path);

            File file=new File(resource.getPath());
            for (File listFile : file.listFiles()) {
                String absolutePath = listFile.getAbsolutePath();
                absolutePath=absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));
                absolutePath=absolutePath.replace("\\",".");

                try {
                    Class<?> aClass = classLoader.loadClass(absolutePath);
                    if (aClass.isAnnotationPresent(Commponent.class)) {
                        //获取beanName
                        Commponent commponentAnnotation = aClass.getAnnotation(Commponent.class);
                        String beanName=commponentAnnotation.value();


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

                        //判断该类是单例加载还是多例加载,没有Scope注解表示多例
                        if (aClass.isAnnotationPresent(Scope.class)) {
                            Scope annotation = aClass.getAnnotation(Scope.class);
                            String value = annotation.value();
                            beanDefinition.setScope(value);
                        }else{
                            beanDefinition.setScope("singleton");
                        }

                        beanDefinitionMap.put(beanName,beanDefinition);
                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

4.Test类修改,测试方法有效性

package com.nickel;


import com.spring.NickelAnnotationConfigApplicationContext;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:16
 */
public class Test {
    public static void main(String[] args) {
        NickelAnnotationConfigApplicationContext context=new NickelAnnotationConfigApplicationContext(NickelAppConfig.class);
        System.out.println(context.getBean("userService"));
        System.out.println(context.getBean("userService"));
    }
}

在这里插入图片描述

五.Spring实现初始化,初始化前、初始化后的方法

5.1初始化前方法实现

由于spring实现初始化的方法是实现接口InitializingBean,同时实现接口里面afterPropertiesSet方法

1.创建InitializingBean接口,在接口中添加afterPropertiesSet方法

package com.spring;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 15:03
 */
public interface InitializingBean {
    void afterPropertiesSet();
}

在这里插入图片描述

2.在创建bean的时候,判断方法是否实现InitializingBean接口,实现接口转化后实现初始化方法

package com.spring;

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

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:20
 */
public class NickelAnnotationConfigApplicationContext {

    private Class scanConfig;
    private Map<String,BeanDefinition> beanDefinitionMap=new HashMap<>();
    private Map<String,Object> singletonObjects=new HashMap<>();

    public NickelAnnotationConfigApplicationContext(Class scanConfig){
        this.scanConfig=scanConfig;

        //扫描逻辑
        scan(scanConfig);

        //创建bean
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            String beanName=entry.getKey();
            BeanDefinition beanDefinition= entry.getValue();
            if (beanDefinition.getScope().equals("singleton")) {
                Object singletonBean=createBean(beanName,beanDefinition);
                singletonObjects.put(beanName,singletonBean);
            }
        }

    }

    public Object getBean(String beanName){
        if (!beanDefinitionMap.containsKey(beanName)) {
           throw new NullPointerException();
        }

        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if(beanDefinition.getScope().equals("singleton")){
           Object singletonBean=singletonObjects.get(beanName);
           if(singletonBean==null){
               singletonBean=createBean(beanName,beanDefinition);
               singletonObjects.put(beanName,singletonBean);
           }
           return singletonBean;
        }else{
            return createBean(beanName,beanDefinition);
        }
    }

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

            if (instance instanceof InitializingBean) {
                ((InitializingBean)instance).afterPropertiesSet();
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        return instance;
    }

    private void scan(Class scanConfig) {
        if (scanConfig.isAnnotationPresent(CommponentScan.class)) {
            CommponentScan commponentScan =(CommponentScan) scanConfig.getAnnotation(CommponentScan.class);
            String path=commponentScan.value();
            path=path.replace(".","/");


            //通过ApplicationContext来加载该类
            ClassLoader classLoader = NickelAnnotationConfigApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(path);

            File file=new File(resource.getPath());
            for (File listFile : file.listFiles()) {
                String absolutePath = listFile.getAbsolutePath();
                absolutePath=absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));
                absolutePath=absolutePath.replace("\\",".");

                try {
                    Class<?> aClass = classLoader.loadClass(absolutePath);
                    if (aClass.isAnnotationPresent(Commponent.class)) {
                        //获取beanName
                        Commponent commponentAnnotation = aClass.getAnnotation(Commponent.class);
                        String beanName=commponentAnnotation.value();


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

                        //判断该类是单例加载还是多例加载,没有Scope注解表示多例
                        if (aClass.isAnnotationPresent(Scope.class)) {
                            Scope annotation = aClass.getAnnotation(Scope.class);
                            String value = annotation.value();
                            beanDefinition.setScope(value);
                        }else{
                            beanDefinition.setScope("singleton");
                        }

                        beanDefinitionMap.put(beanName,beanDefinition);
                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在这里插入图片描述

3.Test测试类测试初始化的方法

package com.nickel;

import com.nickel.service.UserService;
import com.spring.NickelAnnotationConfigApplicationContext;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:16
 */
public class Test {
    public static void main(String[] args) {
        NickelAnnotationConfigApplicationContext context=new NickelAnnotationConfigApplicationContext(NickelAppConfig.class);
//        System.out.println(context.getBean("userService"));
//        System.out.println(context.getBean("userService"));
          UserService userService = (UserService)context.getBean("userService");
         userService.test();
    }
}

在这里插入图片描述

5.2实现初始化前的方法

1.创建BeanPostProcess接口,在接口定义两个方法postProcessBeforeInitialization和postProcessAfterInitialization

package com.spring;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 15:44
 */
public interface BeanPostProcess {
    default Object postProcessBeforeInitialization(Object bean, String beanName){
        return bean;
    }

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

2.定义一个方法NickelBeanPostProcess实现BeanPostProcess方法

package com.nickel.service;

import com.spring.BeanPostProcess;
import com.spring.Commponent;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 15:50
 */
@Commponent
public class NickelBeanPostProcss implements BeanPostProcess {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        return BeanPostProcess.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        if(beanName.equals("userService")){
            System.out.println("userService初始化后");
        }
        return BeanPostProcess.super.postProcessAfterInitialization(bean, beanName);
    }
}

说明:由于该方法要被spring进行管理,那么必须要在改类上面添加Commponent注解,这样类才会被加载

3.改造扫描方法,使得BeanPostProcess能够被加载,创建beanPostProcessList存放所有的BeanPostProcess方法

package com.spring;

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.net.FileNameMap;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:20
 */
public class NickelAnnotationConfigApplicationContext {

    private Class scanConfig;
    private Map<String,BeanDefinition> beanDefinitionMap=new HashMap<>();
    private Map<String,Object> singletonObjects=new HashMap<>();
    private List<BeanPostProcess> beanPostProcessList=new ArrayList<>();

    public NickelAnnotationConfigApplicationContext(Class scanConfig){
        this.scanConfig=scanConfig;

        //扫描逻辑
        scan(scanConfig);

        //创建bean
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            String beanName=entry.getKey();
            BeanDefinition beanDefinition= entry.getValue();
            if (beanDefinition.getScope().equals("singleton")) {
                Object singletonBean=createBean(beanName,beanDefinition);
                singletonObjects.put(beanName,singletonBean);
            }
        }

    }

    public Object getBean(String beanName){
        if (!beanDefinitionMap.containsKey(beanName)) {
           throw new NullPointerException();
        }

        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if(beanDefinition.getScope().equals("singleton")){
           Object singletonBean=singletonObjects.get(beanName);
           if(singletonBean==null){
               singletonBean=createBean(beanName,beanDefinition);
               singletonObjects.put(beanName,singletonBean);
           }
           return singletonBean;
        }else{
            return createBean(beanName,beanDefinition);
        }
    }

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

            for (BeanPostProcess beanPostProcess : beanPostProcessList) {
                instance=beanPostProcess.postProcessBeforeInitialization(instance,beanName);
            }

            if (instance instanceof InitializingBean) {
                ((InitializingBean)instance).afterPropertiesSet();
            }

            for (BeanPostProcess beanPostProcess : beanPostProcessList) {
                instance=beanPostProcess.postProcessAfterInitialization(instance,beanName);
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        return instance;
    }

    private void scan(Class scanConfig) {
        if (scanConfig.isAnnotationPresent(CommponentScan.class)) {
            CommponentScan commponentScan =(CommponentScan) scanConfig.getAnnotation(CommponentScan.class);
            String path=commponentScan.value();
            path=path.replace(".","/");


            //通过ApplicationContext来加载该类
            ClassLoader classLoader = NickelAnnotationConfigApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(path);

            File file=new File(resource.getPath());
            for (File listFile : file.listFiles()) {
                String absolutePath = listFile.getAbsolutePath();
                absolutePath=absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));
                absolutePath=absolutePath.replace("\\",".");

                try {
                    Class<?> aClass  = classLoader.loadClass(absolutePath);
                    if (aClass.isAnnotationPresent(Commponent.class)) {
                        //判断是否实现BeanPostProcess方法
                        if (BeanPostProcess.class.isAssignableFrom(aClass)) {
                            BeanPostProcess beanPostProcess = (BeanPostProcess) aClass.getConstructor().newInstance();
                            beanPostProcessList.add(beanPostProcess);
                        }else{
                            //获取beanName
                            Commponent commponentAnnotation = aClass.getAnnotation(Commponent.class);
                            String beanName=commponentAnnotation.value();


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

                            //判断该类是单例加载还是多例加载,没有Scope注解表示多例
                            if (aClass.isAnnotationPresent(Scope.class)) {
                                Scope annotation = aClass.getAnnotation(Scope.class);
                                String value = annotation.value();
                                beanDefinition.setScope(value);
                            }else{
                                beanDefinition.setScope("singleton");
                            }

                            beanDefinitionMap.put(beanName,beanDefinition);
                        }


                    }
                } catch (ClassNotFoundException | NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.NickelBeanPostProcessor里面实现切面逻辑

4.1创建UserInterface接口

package com.nickel.service;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 16:45
 */
public interface UserInterface {
    public void test();
}

在这里插入图片描述

4.2在UserService中实现接口

package com.nickel.service;

import com.spring.Commponent;
import com.spring.InitializingBean;
import com.spring.Scope;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:43
 */
@Commponent("userService")
@Scope("singleton")
public class UserService implements InitializingBean,UserInterface {

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

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

在这里插入图片描述

4.3在代理中配置相关切面的逻辑

package com.nickel.service;

import com.spring.BeanPostProcess;
import com.spring.Commponent;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 15:50
 */
@Commponent
public class NickelBeanPostProcss implements BeanPostProcess {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        if(beanName.equals("userService")){
           //使用jdk动态代理
            Object proxyInstance = Proxy.newProxyInstance(NickelBeanPostProcss.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;
    }
}

在这里插入图片描述

4.4在测试类中进行测试

package com.nickel;

import com.nickel.service.UserInterface;
import com.nickel.service.UserService;
import com.spring.NickelAnnotationConfigApplicationContext;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:16
 */
public class Test {
    public static void main(String[] args) {
        NickelAnnotationConfigApplicationContext context=new NickelAnnotationConfigApplicationContext(NickelAppConfig.class);
//        System.out.println(context.getBean("userService"));
//        System.out.println(context.getBean("userService"));
        UserInterface userService = (UserInterface)context.getBean("userService");
         userService.test();
    }
}

在这里插入图片描述
说明:由于代理的对象是接口,所以此时返回的对象是接口对象,这是需要转化为接口。

五.Spring实现Autowired自动注入

5.1创建自动注入对象

package com.spring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:21
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowired {

}

在这里插入图片描述

5.2在UserService创建注入对象

package com.nickel.service;

import com.spring.Autowired;
import com.spring.Commponent;
import com.spring.InitializingBean;
import com.spring.Scope;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:43
 */
@Commponent("userService")
@Scope("singleton")
public class UserService implements InitializingBean,UserInterface {

    @Autowired
    private OrderService orderService;

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

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

在这里插入图片描述

5.3在spring加载的时候,获取autowire注解

package com.spring;

import java.beans.Introspector;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.FileNameMap;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:20
 */
public class NickelAnnotationConfigApplicationContext {

    private Class scanConfig;
    private Map<String,BeanDefinition> beanDefinitionMap=new HashMap<>();
    private Map<String,Object> singletonObjects=new HashMap<>();
    private List<BeanPostProcess> beanPostProcessList=new ArrayList<>();

    public NickelAnnotationConfigApplicationContext(Class scanConfig){
        this.scanConfig=scanConfig;

        //扫描逻辑
        scan(scanConfig);

        //创建bean
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            String beanName=entry.getKey();
            BeanDefinition beanDefinition= entry.getValue();
            if (beanDefinition.getScope().equals("singleton")) {
                Object singletonBean=createBean(beanName,beanDefinition);
                singletonObjects.put(beanName,singletonBean);
            }
        }

    }

    public Object getBean(String beanName){
        if (!beanDefinitionMap.containsKey(beanName)) {
           throw new NullPointerException();
        }

        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if(beanDefinition.getScope().equals("singleton")){
           Object singletonBean=singletonObjects.get(beanName);
           if(singletonBean==null){
               singletonBean=createBean(beanName,beanDefinition);
               singletonObjects.put(beanName,singletonBean);
           }
           return singletonBean;
        }else{
            return createBean(beanName,beanDefinition);
        }
    }

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

            for (Field field : clazz.getDeclaredFields()) {
                if (field.isAnnotationPresent(Autowired.class)) {
                    field.setAccessible(true);
                    //获取方法中类型的对象
                    Object object= Introspector.decapitalize(field.getType().getSimpleName());
                    field.set(instance,getBean(object.toString()));
                }
            }

            for (BeanPostProcess beanPostProcess : beanPostProcessList) {
                instance=beanPostProcess.postProcessBeforeInitialization(instance,beanName);
            }

            if (instance instanceof InitializingBean) {
                ((InitializingBean)instance).afterPropertiesSet();
            }

            for (BeanPostProcess beanPostProcess : beanPostProcessList) {
                instance=beanPostProcess.postProcessAfterInitialization(instance,beanName);
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        return instance;
    }

    private void scan(Class scanConfig) {
        if (scanConfig.isAnnotationPresent(CommponentScan.class)) {
            CommponentScan commponentScan =(CommponentScan) scanConfig.getAnnotation(CommponentScan.class);
            String path=commponentScan.value();
            path=path.replace(".","/");


            //通过ApplicationContext来加载该类
            ClassLoader classLoader = NickelAnnotationConfigApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(path);

            File file=new File(resource.getPath());
            for (File listFile : file.listFiles()) {
                String absolutePath = listFile.getAbsolutePath();
                absolutePath=absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));
                absolutePath=absolutePath.replace("\\",".");

                try {
                    Class<?> aClass  = classLoader.loadClass(absolutePath);
                    if (aClass.isAnnotationPresent(Commponent.class)) {
                        //判断是否实现BeanPostProcess方法
                        if (BeanPostProcess.class.isAssignableFrom(aClass)) {
                            BeanPostProcess beanPostProcess = (BeanPostProcess) aClass.getConstructor().newInstance();
                            beanPostProcessList.add(beanPostProcess);
                        }else{
                            //获取beanName
                            Commponent commponentAnnotation = aClass.getAnnotation(Commponent.class);
                            String beanName=commponentAnnotation.value();


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

                            //判断该类是单例加载还是多例加载,没有Scope注解表示多例
                            if (aClass.isAnnotationPresent(Scope.class)) {
                                Scope annotation = aClass.getAnnotation(Scope.class);
                                String value = annotation.value();
                                beanDefinition.setScope(value);
                            }else{
                                beanDefinition.setScope("singleton");
                            }

                            beanDefinitionMap.put(beanName,beanDefinition);
                        }


                    }
                } catch (ClassNotFoundException | NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在这里插入图片描述

六.Spring实现NickelValue注解上面的value直接赋值给属性

在这里插入图片描述

1.创建NickelValue注解对象

package com.nickel.service;

import com.spring.Autowired;
import com.spring.Commponent;
import com.spring.InitializingBean;
import com.spring.Scope;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:43
 */
@Commponent("userService")
@Scope("singleton")
public class UserService implements InitializingBean,UserInterface {

    @Autowired
    private OrderService orderService;

    @NickelValue("Nickel")
    private String name;

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

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

2.在UserService中使用NickelValue对象

package com.nickel.service;

import com.spring.Autowired;
import com.spring.Commponent;
import com.spring.InitializingBean;
import com.spring.Scope;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:43
 */
@Commponent("userService")
@Scope("singleton")
public class UserService implements InitializingBean,UserInterface {

    @Autowired
    private OrderService orderService;

    @NickelValue("Nickel")
    private String name;

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

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

在这里插入图片描述

3.定义实现接口BeanPostProcess的实现方法

package com.nickel.service;

import com.spring.BeanPostProcess;
import com.spring.Commponent;

import java.lang.reflect.Field;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 17:42
 */
@Commponent
public class NickelValueBeanProcess implements BeanPostProcess {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        for (Field field : bean.getClass().getDeclaredFields()) {
            if (field.isAnnotationPresent(NickelValue.class)) {
                field.setAccessible(true);
                try {
                    field.set(bean,field.getAnnotation(NickelValue.class).value());
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        return bean;
    }
}

说明:注意必须添加Commponent注解

4.执行test方法

在这里插入图片描述

七.bean对象中获取spring加载的beanName

7.1创建BeanNameAware接口

package com.nickel.service;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 17:53
 */
public interface BeanNameAware {
    void setBeanName(String name);
}

在这里插入图片描述

7.2UserService实现BeanNameAware接口

package com.nickel.service;

import com.spring.Autowired;
import com.spring.Commponent;
import com.spring.InitializingBean;
import com.spring.Scope;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:43
 */
@Commponent("userService")
@Scope("singleton")
public class UserService implements InitializingBean,UserInterface,BeanNameAware{

    @Autowired
    private OrderService orderService;

    @NickelValue("Nickel")
    private String name;

    private String beanName;

    public void test(){
        System.out.println("test");
        System.out.println(orderService);
        System.out.println(name);
        System.out.println("获取beanName的值"+beanName);
    }

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

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


在这里插入图片描述

7.3NickelAnnotationConfigApplicationContext实现这个接口的方法

package com.spring;

import com.nickel.service.BeanNameAware;
import com.nickel.service.NickelValue;

import java.beans.Introspector;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.FileNameMap;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Nickel
 * @version 1.0
 * @date 2023/7/5 8:20
 */
public class NickelAnnotationConfigApplicationContext {

    private Class scanConfig;
    private Map<String,BeanDefinition> beanDefinitionMap=new HashMap<>();
    private Map<String,Object> singletonObjects=new HashMap<>();
    private List<BeanPostProcess> beanPostProcessList=new ArrayList<>();

    public NickelAnnotationConfigApplicationContext(Class scanConfig){
        this.scanConfig=scanConfig;

        //扫描逻辑
        scan(scanConfig);

        //创建bean
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            String beanName=entry.getKey();
            BeanDefinition beanDefinition= entry.getValue();
            if (beanDefinition.getScope().equals("singleton")) {
                Object singletonBean=createBean(beanName,beanDefinition);
                singletonObjects.put(beanName,singletonBean);
            }
        }

    }

    public Object getBean(String beanName){
        if (!beanDefinitionMap.containsKey(beanName)) {
           throw new NullPointerException();
        }

        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if(beanDefinition.getScope().equals("singleton")){
           Object singletonBean=singletonObjects.get(beanName);
           if(singletonBean==null){
               singletonBean=createBean(beanName,beanDefinition);
               singletonObjects.put(beanName,singletonBean);
           }
           return singletonBean;
        }else{
            return createBean(beanName,beanDefinition);
        }
    }

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

            for (Field field : clazz.getDeclaredFields()) {
                if (field.isAnnotationPresent(Autowired.class)) {
                    field.setAccessible(true);
                    //获取方法中类型的对象
                    Object object= Introspector.decapitalize(field.getType().getSimpleName());
                    field.set(instance,getBean(object.toString()));
                }
            }

            for (BeanPostProcess beanPostProcess : beanPostProcessList) {
                instance=beanPostProcess.postProcessBeforeInitialization(instance,beanName);
            }

            if (instance instanceof InitializingBean) {
                ((InitializingBean)instance).afterPropertiesSet();
            }

            if (instance instanceof BeanNameAware) {
                ((BeanNameAware)instance).setBeanName(beanName);
            }

            for (BeanPostProcess beanPostProcess : beanPostProcessList) {
                instance=beanPostProcess.postProcessAfterInitialization(instance,beanName);
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        return instance;
    }

    private void scan(Class scanConfig) {
        if (scanConfig.isAnnotationPresent(CommponentScan.class)) {
            CommponentScan commponentScan =(CommponentScan) scanConfig.getAnnotation(CommponentScan.class);
            String path=commponentScan.value();
            path=path.replace(".","/");


            //通过ApplicationContext来加载该类
            ClassLoader classLoader = NickelAnnotationConfigApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(path);

            File file=new File(resource.getPath());
            for (File listFile : file.listFiles()) {
                String absolutePath = listFile.getAbsolutePath();
                absolutePath=absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));
                absolutePath=absolutePath.replace("\\",".");

                try {
                    Class<?> aClass  = classLoader.loadClass(absolutePath);
                    if (aClass.isAnnotationPresent(Commponent.class)) {
                        //判断是否实现BeanPostProcess方法
                        if (BeanPostProcess.class.isAssignableFrom(aClass)) {
                            BeanPostProcess beanPostProcess = (BeanPostProcess) aClass.getConstructor().newInstance();
                            beanPostProcessList.add(beanPostProcess);
                        }else{
                            //获取beanName
                            Commponent commponentAnnotation = aClass.getAnnotation(Commponent.class);
                            String beanName=commponentAnnotation.value();


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

                            //判断该类是单例加载还是多例加载,没有Scope注解表示多例
                            if (aClass.isAnnotationPresent(Scope.class)) {
                                Scope annotation = aClass.getAnnotation(Scope.class);
                                String value = annotation.value();
                                beanDefinition.setScope(value);
                            }else{
                                beanDefinition.setScope("singleton");
                            }

                            beanDefinitionMap.put(beanName,beanDefinition);
                        }


                    }
                } catch (ClassNotFoundException | NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在这里插入图片描述

7.4测试结果

在这里插入图片描述

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

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

相关文章

网工内推 | 国内知名云服务商,IE证书优先,最高18k*15薪

01 UCloud 招聘岗位&#xff1a;网络工程师 职责描述&#xff1a; 1、负责UCloud全球骨干网或数据中心网络工作&#xff0c;包括设备技术选型、架构运营方案设计、日常运维支持&#xff1b; 2、持续提升网络稳定性与性能。 任职要求&#xff1a; 1、本科及以上学历&#xff…

Vue中使用 file-saver 实现导出excel文件

1、先下载一波 file-saver yarn add file-saver 2、封装导出-接口的请求 需要修改请求的数据类型 responsetype 的值为 blob responsetype 默认值是 json 可省略不写 // 导出excel export function exportExcel() {return http({url: /sys/user/export,responseType: b…

TOPSIS法

优劣解距离法&#xff1a;评价类模型&#xff0c;有准确的评判标准后得到评分。 构造计算评分的公式&#xff1a; (x-min)/(max-min) 或(x-min)/((max-x)(x-min)) 指标类型 极大型指标&#xff1a;越大越好。 极小型指标&#xff1a;越小越好。 中间性指标&#xff1a;既…

JavaWeb实现学生管理系统

JavaWeb实现学生管理系统 一、项目介绍二、项目结构三、前期准备1.配置maven环境&#xff0c;在pom.xml配置文件中配置项目所依赖的jar包2.在MySql数据库中&#xff0c;创建登录注册表login和学生信息表student&#xff08;1&#xff09;登录注册表login&#xff08;2&#xff…

【C++】继承 | 基类和派生类对象赋值转换 | 派生类的默认成员函数 | 菱形继承

目录 1.继承的概念及定义 1.1继承的概念 1.2 继承定义 1.2.1定义格式 1.2.2继承关系和访问限定符 1.2.3继承基类成员访问方式的变化 2.基类和派生类对象赋值转换 3.继承中的作用域 4.派生类的默认成员函数 5.继承与友元 6. 继承与静态成员 7. 菱形继承 1.继承的概念…

【InsCode Stable Diffusion美图活动一期】——海边跳舞的少女

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

window平台下MSVC2015编译Libyuv静态库 动态库

window平台下MSVC2015编译Libyuv静态库 动态库 编译步骤一、环境准备1.1 下载libyuv源码1.2 下载安装cmake&#xff1a;1.3 安装MobaXterm&#xff08;终端工具&#xff09; 二、编译生成静态&#xff0c;动态库2.1 cmake编译生成Visual Studio工程2.2 使用Visual Studio打开YU…

怎么从视频中提取音频?分享三个方法给大家!

如何从视频中提取音频&#xff1f;当我们观看视频时&#xff0c;经常会听到很好听的音乐&#xff0c;或者希望下载视频课程的音频以便随时学习。有时候&#xff0c;某些音频可能没有单独的音源或无法下载。那么&#xff0c;有什么方法可以将视频中的音频提取出来呢&#xff1f;…

第五章:Mask R-CNN网络详解

(目标检测篇&#xff09;系列文章目录 第一章:R-CNN网络详解 第二章:Fast R-CNN网络详解 第三章:Faster R-CNN网络详解 第四章:SSD网络详解 第五章:Mask R-CNN网络详解 第六章:YOLO v1网络详解 第七章:YOLO v2网络详解 第八章:YOLO v3网络详解 文章目录 系列文章目录技…

Openlayers实战:自定义放大缩小,显示zoom等级

Openlayers地图中,默认的zoom组件是在左上角,这个组件很重要,方便大家来操控地图。在实际项目中,大家往往要改写这个组件,通常会放置到右下角,方便鼠标操作。 在我们的实战课程里,自定义了放大缩小,并增加了显示zoom等级的功能,实际的项目中往往都是这样办理的。 效果…

4、CCesium鼠标点击事件

在地图中添加鼠标点击事件&#xff0c;与web端cesium基本类似&#xff0c;我们使用上一个的示例&#xff0c;在上一个的示例中进行修改。 1、建一个类Handler&#xff0c;类中又个静态函数mouseUp&#xff0c;函数只在控制台输出信息 2、声明变量handler&#xff0c;并创建Scr…

java环境配置为1.8jdk为什么cmd java -version查看版本是17或者11

1、查看你的环境变量中Path的配置&#xff0c;确认%java_home%/bin在path值的第一个。 2、在cmd中输入echo %path%&#xff0c;看一下实际有效的path值是什么&#xff0c;其中的java配置对不对 3、oracle也自带一个jdk&#xff0c;如果你在配置环境变量时&#xff0c;将jdk配在…

m4a格式怎么转换成mp3,这几个方法分享给大家!

m4a是一种音频格式&#xff0c;它与mp3格式有一些区别。据说m4a是AAC的扩展名之一&#xff0c;它是Apple对MP3的回应&#xff0c;主要用于Mac环境下的压缩音频格式。随着iTunes Store的兴起&#xff0c;m4a在通过在线音乐商店购买音乐方面变得非常流行。然而&#xff0c;尽管许…

正则表达式测试(一)

一、匹配上1,2,3 三种字符串 测试地址&#xff1a;访问 二、匹配上1,2,3 三种字符串 三、匹配上1,2,3 三种字符串 四、匹配上第一个字符串 五、反向引用 反向引用还可以将通用资源指示符 (URI) 分解为其组件 举例&#xff1a;将下面的 URI 分解为协议&#xff08;ftp、http 等…

Stable Diffusion 图生图-蒙版重绘,Controlnet未生效的一个场景

首先感谢秋叶大佬的整合包&#xff01;&#xff01;&#xff01; 致敬所有在为AI绘画付出努力的大佬&#xff01;&#xff01;&#xff01; 省流&#xff1a;绘图时禁用插件sd-webui-segment-anything 场景&#xff1a;在电商换装场景下&#xff0c;为图中角色换衣服,使用了2个…

力扣 -- 198. 打家劫舍

题目链接&#xff1a;198. 打家劫舍 - 力扣&#xff08;LeetCode&#xff09; 在看这道题之前可以先看看按摩师的博文&#xff0c;写的细节更详细。(4条消息) 力扣 -- 面试题 17.16. 按摩师_高比拜仁0824的博客-CSDN博客 下面是用动态规划的思想解决这道题的过程&#xff0c…

MySQL:数据库的基本操作及数据库的三大数据类型

目录 一、创建数据库 二、删除数据库 三、查询数据 四、在数据库使用Linux命令 五、数据库的编码方式以及校验规则 1、查看MySQL支持的所有编码方式 2、查看某一种编码方式支持的所有校验规则 3、查看所有的编码方式和校验规则 4、查看本地数据库使用的编码方式和校验规…

-Xss / -XX:ThreadStackSize

-Xss / -XX:ThreadStackSize指定线程最大栈空间jdk1.4里默认的栈大小是256KBjdk1.5里默认的栈大小为1M这个参数直接会影响创建线程数量&#xff0c;值越小创建线程数越多&#xff1b; &#xff08;估算jvm进程的最大线程数&#xff09;这个参数直接决定了函数可调用的最大深度&…

【Docker】完整的搭建和发布过程

【Docker】完整的搭建和发布过程 【一】shell和ftp工具选择【二】安装Docker【1】查看系统的内核版本【2】yum更新到最新版本【3】安装Docker所需的依赖包【4】设置Docker的yum的源【5】查看仓库所有Docker版本【6】安装Docker【7】启动Docker并添加开机自启动【8】查看Docker版…

秋招提前批!大厂offer的捷径!

前言 又是一年秋招季&#xff01;年年岁岁花相似&#xff0c;岁岁年年人不同。 今天&#xff0c;博主在牛客上看到一个帖子&#xff0c;24届校招提前批已经开始了&#xff01; 24届大厂提前批 首先&#xff0c;跟大家科普一下提前批的概念&#xff0c;提前批是指企业在校园招…