根据java反射-手写springIoC

news2024/10/6 2:30:45

我们都知道,Spring框架的IOC是基于Java反射机制实现的,下面我们先回顾一下java反射。

回顾Java反射

Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。简单来说,反射机制指的是程序在运行时能够获取自身的信息。

要想解剖一个类,必须先要获取到该类的Class对象。而剖析一个类或用反射解决具体的问题就是使用相关API (1)java.lang.Class(2)java.lang.reflect,所以,Class对象是反射的根源

自定义类

public class Car {
    //属性
    private String name;
    private int age;
    private String color;

    //无参数构造
    public Car() {
    }

    //有参数构造
    public Car(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }

    //普通方法
    private void run() {
        System.out.println("私有方法-run.....");
    }

    //get和set方法
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public String toString() {
        return "Car{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", color='" + color + '\'' +
                '}';
    }
}

测试类

public class TestCar {
    /**
     * //1、获取Class对象多种方式
     *
     * @throws ClassNotFoundException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    @Test
    public void test01() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //1 类名.class
        Class clazz1 = Car.class;

        //2 对象.getClass()
        Class clazz2 = new Car().getClass();

        //3 Class.forName("全路径")
        Class clazz3 = Class.forName("com.zhubayi.reflect.Car");

        //实例化
        Car car = (Car) clazz3.getConstructor().newInstance();
        System.out.println(car);
    }

    /**
     * 获取构造方法
     */
    @Test
    public void test02() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<Car> clazz = Car.class;
        // getConstructors()获取所有public的构造方法
        //Constructor[] constructors = clazz.getConstructors();
        // getDeclaredConstructors()获取所有的构造方法public  private
        Constructor[] constructors = clazz.getDeclaredConstructors();
        for (Constructor c : constructors) {
            System.out.println("方法名称:" + c.getName() + " 参数个数:" + c.getParameterCount());
        }
        //指定有参数构造创建对象
        //1 构造public
//        Constructor c1 = clazz.getConstructor(String.class, int.class, String.class);
//        Car car1 = (Car)c1.newInstance("夏利", 10, "红色");
//        System.out.println(car1);

        //2 构造private
        Constructor c2 = clazz.getDeclaredConstructor(String.class, int.class, String.class);
        c2.setAccessible(true);
        Car car2 = (Car) c2.newInstance("捷达", 15, "白色");
        System.out.println(car2);
    }

    //3、获取属性
    @Test
    public void test03() throws Exception {
        Class clazz = Car.class;
        Car car = (Car) clazz.getDeclaredConstructor().newInstance();
        //获取所有public属性
        //Field[] fields = clazz.getFields();
        //获取所有属性(包含私有属性)
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (field.getName().equals("name")) {
                //设置允许访问
                field.setAccessible(true);
                field.set(car, "五菱宏光");
                System.out.println(car);
            }
            System.out.println(field.getName());
        }
    }

    //4、获取方法
    @Test
    public void test04() throws Exception {
        Car car = new Car("奔驰", 10, "黑色");
        Class clazz = car.getClass();
        //1 public方法
        Method[] methods = clazz.getMethods();
        for (Method m1 : methods) {
            //System.out.println(m1.getName());
            //执行方法 toString
            if (m1.getName().equals("toString")) {
                String invoke = (String) m1.invoke(car);
                //System.out.println("toString执行了:"+invoke);
            }
        }
        //2 private方法
        Method[] methodsAll = clazz.getDeclaredMethods();
        for (Method m : methodsAll) {
            //执行方法 run
            if (m.getName().equals("run")) {
                m.setAccessible(true);
                m.invoke(car);
            }
        }

    }
}

实现Spring的IoC

我们知道,IoC(控制反转)和DI(依赖注入)是Spring里面核心的东西,那么,我们如何自己手写出这样的代码呢?下面我们就一步一步写出Spring框架最核心的部分。

添加依赖

<dependencies>
    <!--junit5测试-->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.3.1</version>
    </dependency>
</dependencies>

定义注解,我们通过注解的形式加载bean与实现依赖注入

bean注解

package com.zhubayi.spring.core.annotation;

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

/**
 * @author zhubayi
 * @Description
 */
@Target(ElementType.TYPE)//class interface
@Retention(RetentionPolicy.RUNTIME)
public @interface Bean {

}

依赖注入注解

package com.zhubayi.spring.core.annotation;

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

/**
 * @author zhubayi
 * @Description
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Di {

}

说明:上面两个注解可以随意取名

准备测试需要的bean

创建UserDao接口

package com.zhubayi.spring6.test.dao;

/**
 * @author zhubayi
 * @Description
 */
public interface UserDao {
    void print();
}

创建UserDaoImpl实现

package com.zhubayi.spring6.test.dao.impl;

import com.zhubayi.spring.core.annotation.Bean;
import com.zhubayi.spring6.test.dao.UserDao;

/**
 * @author zhubayi
 * @Description
 */
@Bean
public class UserDaoImpl implements UserDao {
    @Override
    public void print() {
        System.out.println("Dao方法执行成功!");
    }
}

创建UserService接口

package com.zhubayi.spring6.test.service;

/**
 * @author zhubayi
 * @Description
 */
public interface UserService {
    void out();
}

创建UserServiceImpl实现类

package com.zhubayi.spring6.test.service.impl;

import com.zhubayi.spring.core.annotation.Bean;
import com.zhubayi.spring.core.annotation.Di;
import com.zhubayi.spring6.test.dao.UserDao;
import com.zhubayi.spring6.test.service.UserService;

/**
 * @author zhubayi
 * @Description
 */
@Bean
public class UserServiceImpl implements UserService {
    @Override
    public void out() {
        System.out.println("Service层执行结束");
    }
}

定义bean容器接口

package com.zhubayi.spring.core;

/**
 * @author zhubayi
 * @Description
 */
public interface ApplicationContext {
    /**
     * 得到bean
     *
     * @param clazz clazz
     * @return {@link Object}
     */
    Object getBean(Class clazz);
}

编写注解bean容器接口实现

AnnotationApplicationContext基于注解扫描bean

package com.zhubayi.spring.core;

import java.util.HashMap;

public class AnnotationApplicationContext implements ApplicationContext {

    //存储bean的容器
    private HashMap<Class, Object> beanFactory = new HashMap<>();

    @Override
    public Object getBean(Class clazz) {
        return beanFactory.get(clazz);
    }

    /**
     * 根据包扫描加载bean
     * @param basePackage
     */
    public AnnotationApplicationContext(String basePackage) {
        
    }
}

编写扫描bean逻辑

我们通过构造方法传入包的base路径,扫描被@Bean注解的java对象,完整代码如下:

package com.zhuabyi.spring.core;

import com.atguigu.spring.core.annotation.Bean;

import java.io.File;
import java.util.HashMap;

public class AnnotationApplicationContext implements ApplicationContext {

    //存储bean的容器
    private HashMap<Class, Object> beanFactory = new HashMap<>();
    private static String rootPath;

    @Override
    public Object getBean(Class clazz) {
        return beanFactory.get(clazz);
    }

    /**
     * 根据包扫描加载bean
     * @param basePackage
     */
    public AnnotationApplicationContext(String basePackage) {
       try {
            //把.替换成\\
            String packageDirName = basePackage.replaceAll("\\.", "\\\\");
            Enumeration<URL> dirs =Thread.currentThread().getContextClassLoader().getResources(packageDirName);
            while (dirs.hasMoreElements()) {
                URL url = dirs.nextElement();
                String filePath = URLDecoder.decode(url.getFile(),"utf-8");
                rootPath = filePath.substring(0, filePath.length()-packageDirName.length());
                loadBean(new File(filePath));
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private  void loadBean(File fileParent) {
        if (fileParent.isDirectory()) {
            File[] childrenFiles = fileParent.listFiles();
            if(childrenFiles == null || childrenFiles.length == 0){
                return;
            }
            for (File child : childrenFiles) {
                if (child.isDirectory()) {
                    //如果是个文件夹就继续调用该方法,使用了递归
                    loadBean(child);
                } else {
                    //通过文件路径转变成全类名,第一步把绝对路径部分去掉
                    String pathWithClass = child.getAbsolutePath().substring(rootPath.length() - 1);
                    //选中class文件
                    if (pathWithClass.contains(".class")) {
                        //    com.xinzhi.dao.UserDao
                        //去掉.class后缀,并且把 \ 替换成 .
                        String fullName = pathWithClass.replaceAll("\\\\", ".").replace(".class", "");
                        try {
                            Class<?> aClass = Class.forName(fullName);
                            //把非接口的类实例化放在map中
                            if(!aClass.isInterface()){
                                Bean annotation = aClass.getAnnotation(Bean.class);
                                if(annotation != null){
                                    Object instance = aClass.newInstance();
                                    //判断一下有没有接口
                                    if(aClass.getInterfaces().length > 0) {
                                        //如果有接口把接口的class当成key,实例对象当成value
                                        System.out.println("正在加载【"+ aClass.getInterfaces()[0] +"】,实例对象是:" + instance.getClass().getName());
                                        beanFactory.put(aClass.getInterfaces()[0], instance);
                                    }else{
                                        //如果没有接口把自己的class当成key,自己实例对象当成value
                                        System.out.println("正在加载【"+ aClass.getName() +"】,实例对象是:" + instance.getClass().getName());
                                        beanFactory.put(aClass, instance);
                                    }
                                }
                            }
                        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

}

java类标识Bean注解

@Bean
public class UserServiceImpl implements UserService
@Bean
public class UserDaoImpl implements UserDao 

测试

package com.zhubayi.spring;

import com.zhubayi.spring.core.AnnotationApplicationContext;
import com.zhubayi.spring.core.ApplicationContext;
import com.zhubayi.spring6.test.service.UserService;
import org.junit.jupiter.api.Test;

/**
 * @author zhubayi
 * @Description
 */
public class SpringIcoTest {
    @Test
    public void testIoc() {
        ApplicationContext applicationContext = new AnnotationApplicationContext("com.zhubayi.spring6.test");
        UserService userService = (UserService)applicationContext.getBean(UserService.class);
        userService.out();
        System.out.println("run success");
    }
  }

结果

正在加载【interface com.zhubayi.spring6.test.dao.UserDao】,实例对象是:com.zhubayi.spring6.test.dao.impl.UserDaoImpl
正在加载【interface com.zhubayi.spring6.test.service.UserService】,实例对象是:com.zhubayi.spring6.test.service.impl.UserServiceImpl
Service层执行结束
run success

依赖注入

只要userDao.print();调用成功,说明就注入成功

package com.zhubayi.spring6.test.service.impl;

import com.zhubayi.spring.core.annotation.Bean;
import com.zhubayi.spring.core.annotation.Di;
import com.zhubayi.spring6.test.dao.UserDao;
import com.zhubayi.spring6.test.service.UserService;

/**
 * @author zhubayi
 * @Description
 */
@Bean
public class UserServiceImpl implements UserService {
    @Di
    private UserDao userDao;
    @Override
    public void out() {
        userDao.print();
        System.out.println("Service层执行结束");
    }
}

在这里插入图片描述
执行以下代码

	@Test
    public void testDi() {
        ApplicationContext applicationContext = new AnnotationApplicationContext("com.zhubayi.spring6.test");
        UserService userService = (UserService)applicationContext.getBean(UserService.class);
        userService.out();
        System.out.println("run success");
    }

执行报错

正在加载【interface com.zhubayi.spring6.test.dao.UserDao】,实例对象是:com.zhubayi.spring6.test.dao.impl.UserDaoImpl
正在加载【interface com.zhubayi.spring6.test.service.UserService】,实例对象是:com.zhubayi.spring6.test.service.impl.UserServiceImpl

java.lang.NullPointerException: Cannot invoke "com.zhubayi.spring6.test.dao.UserDao.print()" because "this.userDao" is null

	at com.zhubayi.spring6.test.service.impl.UserServiceImpl.out(UserServiceImpl.java:18)
	at com.zhubayi.spring.SpringIcoTest.testDi(SpringIcoTest.java:24)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:515)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:171)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:167)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:114)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:59)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:105)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:95)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:71)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:110)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:95)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:71)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:110)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:95)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:71)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:220)
	at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:188)
	at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:202)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:181)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
	at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
	at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)

说明当前userDao是个空对象

依赖注入实现

package com.zhubayi.spring.core;

import com.zhubayi.spring.core.annotation.Bean;
import com.zhubayi.spring.core.annotation.Di;

import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zhubayi
 * @Description
 */
public class AnnotationApplicationContext implements ApplicationContext {
    //存储bean的容器
    private Map<Class, Object> beanFactory = new HashMap<>();
    private static String rootPath;

    /**
     * 得到bean
     *
     * @param clazz clazz
     * @return {@link Object}
     */
    @Override
    public Object getBean(Class clazz) {
        return beanFactory.get(clazz);
    }

    /**
     * 根据包扫描加载bean
     *
     * @param basePackage
     */
    public AnnotationApplicationContext(String basePackage) {
        try {
            //就是把.替换成\\
            String packageDirName = basePackage.replaceAll("\\.", "\\\\");
            Enumeration<URL> dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
            while (dirs.hasMoreElements()) {
                URL url = dirs.nextElement();
                //防止中文乱码
                String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
                //根路径
                rootPath = filePath.substring(0, filePath.length() - packageDirName.length());
                loadBean(new File(filePath));
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        //依赖注入
        loadDi();
    }

    private void loadBean(File fileParent) {
        //是目录
        if (fileParent.isDirectory()) {
            File[] childrenFiles = fileParent.listFiles();
            if (childrenFiles == null || childrenFiles.length == 0) {
                return;
            }
            for (File child : childrenFiles) {
                if (child.isDirectory()) {
                    //如果是个文件夹就继续调用该方法,使用了递归
                    loadBean(child);
                } else {
                    //通过文件路径转变成全类名,第一步把绝对路径部分去掉
                    String pathWithClass = child.getAbsolutePath().substring(rootPath.length() - 1);
                    if (pathWithClass.contains(".class")) {
                        //    com.xinzhi.dao.UserDao
                        //去掉.class后缀,并且把 \ 替换成 .
                        String fullName = pathWithClass.replaceAll("\\\\", ".").replace(".class", "");
                        try {
                            Class<?> aClass = Class.forName(fullName);
                            //把非接口的类实例化放在map中
                            if (!aClass.isInterface()) {
                                Bean annotation = aClass.getAnnotation(Bean.class);
                                if (annotation != null) {
                                    Object instance = aClass.newInstance();
                                    //判断一下有没有接口
                                    if (aClass.getInterfaces().length > 0) {
                                        //如果有接口把接口的class当成key,实例对象当成value
                                        System.out.println("正在加载【" + aClass.getInterfaces()[0] + "】,实例对象是:" + instance.getClass().getName());
                                        beanFactory.put(aClass.getInterfaces()[0], instance);
                                    } else {
                                        //如果没有接口把自己的class当成key,实例对象当成value
                                        System.out.println("正在加载【" + aClass.getName() + "】,实例对象是:" + instance.getClass().getName());
                                        beanFactory.put(aClass, instance);
                                    }
                                }
                            }
                        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    private void loadDi() {
        for (Map.Entry<Class, Object> entry : beanFactory.entrySet()) {
            Object obj = entry.getValue();
            Class<?> aClass = obj.getClass();
            Field[] fields = aClass.getDeclaredFields();
            for (Field field : fields) {
                Di di = field.getAnnotation(Di.class);
                if (di != null) {
                    field.setAccessible(true);
                    try {
                        System.out.println("正在给【" + obj.getClass().getName() + "】属性【" + field.getName() + "】注入值【" + beanFactory.get(field.getType()).getClass().getName() + "】");
                        field.set(obj, beanFactory.get(field.getType()));
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
    }

}

再次执行testDi 方法

正在加载【interface com.zhubayi.spring6.test.dao.UserDao】,实例对象是:com.zhubayi.spring6.test.dao.impl.UserDaoImpl
正在加载【interface com.zhubayi.spring6.test.service.UserService】,实例对象是:com.zhubayi.spring6.test.service.impl.UserServiceImpl
正在给【com.zhubayi.spring6.test.service.impl.UserServiceImpl】属性【userDao】注入值【com.zhubayi.spring6.test.dao.impl.UserDaoImpl】
Dao方法执行成功!
Service层执行结束
run success

执行成功,依赖注入成功

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

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

相关文章

ResNet简单介绍+Pytroch代码实现

文章目录一、背景介绍二、ResNet网络结构1.ResNet34结构示意图2.不同层数的ResNet采用的Block结构。3.不同层数的ResNet网络结构示意图4.实验结果三、Pytroch代码1.代码简单介绍2. 常见ResNet网络代码汇总四、参考文献一、背景介绍 问题&#xff1a; 当网络层数越来越深时&…

Vulkan 编程指南记录

1 创建Vulkan instance 利用CreateInfo结构体指定硬件驱动需要使用的程序信息&#xff0c;这些信息可能会被作为驱动程序的优化依据指定程序需要使用的全局扩展。比如和窗口系统交互的扩展&#xff08;通过glfw库的接口获取&#xff09;。可以通过vkEnumerateInstanceExtensio…

一篇文章全知全能SpringBoot Bean的生命周期

系列文章&#xff1a;https://gamwatcher.blog.csdn.net/article/details/124603278这篇文章也是计划了蛮久的了&#xff0c;一直没写&#xff0c;正所谓大道行思&#xff0c;取则行远&#xff0c;总结也是学习的一种方式。&#x1f648;记得看目录哦1、关于spring1.1 什么是sp…

Spring Security在前端后端分离项目中的使用

Spring Security 是 Spring 家族中的一个安全管理框架&#xff0c;可以和Spring Boot项目很方便的集成。Spring Security框架的两大核心功能&#xff1a;认证和授权 认证&#xff1a; 验证当前访问系统的是不是本系统的用户&#xff0c;并且要确认具体是哪个用户。简单的理解就…

全网最详细的mybatis plus 条件构造器queryWrapper学习,比如and(),eq(),or(),like(),between(),orderByAsc()等方法以及分页操作

文章目录1. 引言2. 结构关系3. 环境配置3.1 引入jar包3.2 创建数据源3.2 创建User实体类3.4 创建UserMapper类3.5 创建UserService类4. 操作演示5. 注意事项1. 引言 mybatis大家都有使用过&#xff0c;既面向对象又灵活可配。不友好的地方是&#xff0c;会随着使用出现大量xml…

C++之缺省参数以及C++的输入输出

文章目录前言一、缺省参数的定义二、缺省参数的分类1.全缺省参数2.半缺省参数三、缺省参数的注意事项1. 半缺省参数必须从右往左依次来给出&#xff0c;不能间接给缺省值2. 缺省参数不能在函数声明和定义中同时出现3. 缺省值必须是常量或者全局变量4. C语言不支持四、C的输入&a…

考虑实时市场联动的电力零售商鲁棒定价策略(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

JavaEE初阶第三课:网络初识

欢迎来到javaee初阶的第三课&#xff0c;这节课我会带大家来初识网络 荔枝目录1.认识IP和端口1.1 IP1.2端口2.认识协议2.1协议分层&#xff08;TCP/IP协议&#xff09;2.2封装与分用2.3两台主机之间的网络通信流程&#xff08;非同一网段&#xff09;3.其他常见名词 解释3.1客户…

电脑老是蓝屏是什么原因?怎么修复蓝屏

电脑老是蓝屏是什么原因&#xff1f;其实电脑蓝屏的原因是有很多种的&#xff0c;每个地方出问题都会导致电脑蓝屏&#xff0c;所以我们要想知道蓝屏的原因&#xff0c;那么就需要一步步的去检测&#xff0c;去排除掉一些可能&#xff0c;才能得出正确的蓝屏原因的答案。 一.什…

MATLAB 数组计算

✅作者简介&#xff1a;人工智能专业本科在读&#xff0c;喜欢计算机与编程&#xff0c;写博客记录自己的学习历程。 &#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&…

Java字典注解的简单实现(AOP)

需求来源 在开发过程中&#xff0c;必不可少会用到字典&#xff0c;例如&#xff0c;数据库字段性别字段可能是这样的&#xff1a;1&#xff1a;男&#xff1b;2&#xff1a;女&#xff0c;在数据存储的时候用1和2&#xff0c;但是在前端展示的时候需要使用男和女&#xff0c;…

有没有人像我一样每次面对sql都很痛苦

今天又操作了一遍sql&#xff0c;这世界上有没有人像我一样&#xff0c;每一次面对mysql都是一次痛苦的经历。 不知道别人怎么想&#xff0c;反正我是这样的。使用mysql从来没有让我快乐过。在数据库里面&#xff0c;最喜欢mongo&#xff0c;当然我也只会mongo。但是每一次使用…

NL-meals、BM3D

常用的高斯滤波或者均值滤波相对都比较简单&#xff0c;即每个窗口的滤波核都是一样的。稍微复杂一些保边滤波如&#xff0c;双边滤波和导向图滤波等。这里介绍几种ffmpeg里面包含的相对比较复杂的滤波算法。计算量不可谓不小。可以通过ffmpeg查看源码实现过程&#xff0c;这里…

RHCE(防火墙)

文章目录一、什么是防火墙二、iptables三、firewalld四、作业一、什么是防火墙 防火墙&#xff1a;防火墙是位于内部网络和外部网络之间的屏障&#xff0c;它按照系统管理员预先定义的规则来控制数据包的进出 防火墙可以分为硬件防火墙和软件防火墙。硬件防火墙是由厂商设计好的…

LongAdder/LongAccumulator类分析

一、LongAdder简介 1.下图是JDK-API文档的的截图信息 我们可以得知这两个类都是1.8开始提供的&#xff0c;并且都具有顶级的并发性。这两类的区别点主要在于LongAdder初始值为0&#xff0c;只能做累加操作&#xff0c;而LongAccumulator可以完成一些复杂的计算&#xff0c;本…

软件设计师考试整理-0-前言

1. 整理初衷 2022年下半年的软考成绩出来了&#xff0c;查了一下&#xff0c;上午58分&#xff0c;下午61分&#xff0c;虽然不高&#xff0c;但是也过了&#xff0c;还是值得开心的&#xff0c;毕竟在最初报考的时候&#xff0c;会的知识点寥寥无几。 先解释下为什么我会报考…

富勒烯C60,131159-39-2,水溶性富勒烯,CARBON C60

产品描述&#xff1a;富勒烯C60与金刚石、石墨是碳的三种同素异形体&#xff0c;富勒烯分子是一种由60个碳原子结合形成的稳定分子&#xff0c;它具有60个顶点和32个面&#xff0c;其中12个为正五边形&#xff0c;20个为正六边形&#xff0c;它形似足球&#xff0c;所以又称为富…

OpenMMLab AI实战营Day2 图像分类

目录 一、图像分类 二、卷积神经网络 三、超越ResNet的图像分类模型 1、神经结构搜索 2、Transformer 3、ConvNext 四、轻量化神经网络 五、Vision Transformer 六、模型学习 七、学习率与优化器调整策略 八、数据增强 一、图像分类 图像分类&#xff1a;识别图像中…

网络骗局丨典型案例分析,大家一起来避雷!

作者&#xff1a;黑蛋因为疫情的困扰&#xff0c;总体经济都不是很好&#xff0c;春节前后&#xff0c;网络诈骗高发期&#xff0c;以下是几种典型案例&#xff0c;一起来看看。比较常见的有以下几种&#xff1a;1、网络购物骗局小红在某平台网购一件产品&#xff0c;几天后&am…

Nacos+Springcloud+mybatis-plus+oracle的整合

NacosSpringcloudmybatis-plusoracle的整合 1、项目结构 2、父类的依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance&q…