实现Spring底层机制(三)

文章目录

  • 阶段4—实现BeanPostProcessor机制
    • 1.文件目录
    • 2.初始化方法实现
        • 1.编写初始化接口InitializingBean.java
        • 2.MonsterService.java实现初始化接口
        • 3.容器中的createBean方法增加初始化逻辑,判断对象类型是否是InitializingBean的子类型,如果是,则转换成初始化接口类型执行初始化方法
    • 3.后置处理器实现
        • 1.编写后置处理器接口BeanPostProcessor.java
        • 2.在组件文件夹下编写后置处理器实现类SunBeanPostProcessor.java会被容器扫描
        • 3.容器类完整代码SunSpringApplicationContext.java
        • 4.结果展示
    • 4.该阶段完成的任务
  • 阶段5—实现AOP机制&Spring底层机制总结
    • 1.实现AOP机制
        • 1.原理分析
        • 2.代码实现
          • 1.文件目录
          • 2.编写接口SmartAnimalable.java
          • 2.编写实现类SmartDog.java
          • 3.编写切面类SmartAnimalAspect.java
          • 4.修改SunBeanPostProcessor.java对SmartDog的getSum方法进行动态代理
          • 5.启动类
          • 6.结果展示
        • 3.该阶段完成的任务
    • 2.Spring底层机制总结
        • 1.bean的生命周期
        • 2.Spring容器的执行流程
        • 3.动态代理和AOP的区别
        • 4.关于后置处理器 + 动态代理的理解
        • 5.AOP的使用方式

阶段4—实现BeanPostProcessor机制

1.文件目录

image-20240222142242669

2.初始化方法实现

1.编写初始化接口InitializingBean.java
package com.sun.spring.processor;

/**
 * 该接口有一个方法afterPropertiesSet是在依赖注入之后调用,即初始化方法
 * @author 孙显圣
 * @version 1.0
 */
public interface InitializingBean {
    void afterPropertiesSet() throws Exception;
}

2.MonsterService.java实现初始化接口
package com.sun.spring.component;

import com.sun.spring.annotation.Autowired;
import com.sun.spring.annotation.Component;
import com.sun.spring.annotation.Scope;
import com.sun.spring.processor.InitializingBean;

/**
 * @author 孙显圣
 * @version 1.0
 */

@Scope(value = "prototype") //指定是多例的
@Component(value = "monsterService")//自定义注解,自动反射创建bean对象,如果指定了value则id为value否则为首字母小写
public class MonsterService implements InitializingBean{
    //自定义注解,按照名字进行依赖注入
    @Autowired
    private MonsterDao monsterDao;

    public void m1() {
        monsterDao.hi();
    }

    //初始化方法
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("MonsterService 的初始化方法被调用!");
    }
}

3.容器中的createBean方法增加初始化逻辑,判断对象类型是否是InitializingBean的子类型,如果是,则转换成初始化接口类型执行初始化方法

3.后置处理器实现

1.编写后置处理器接口BeanPostProcessor.java
package com.sun.spring.processor;


/**
 * @author 孙显圣
 * @version 1.0
 */
public interface BeanPostProcessor {
    //这两个方法会对Spring容器的所有bean生效,切面编程
    //bean初始化方法前调用
    default Object postProcessBeforeInitialization(Object bean, String beanName){
        return bean;
    }

    //bean初始化方法后调用
    default Object postProcessAfterInitialization(Object bean, String beanName){
        return bean;
    }
}

2.在组件文件夹下编写后置处理器实现类SunBeanPostProcessor.java会被容器扫描
package com.sun.spring.component;

import com.sun.spring.annotation.Component;
import com.sun.spring.processor.BeanPostProcessor;

/**
 * 后置处理器,实现了自定义的后置处理器的接口
 *
 * @author 孙显圣
 * @version 1.0
 */
//反射创建bean对象
@Component
public class SunBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        System.out.println("\n后置处理器postProcessBeforeInitialization被调用 bean类型=" + bean.getClass() + "bean名字=" + beanName);
        if (bean instanceof Car) {
            System.out.println("后置处理器发现这个类型是Car类型");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        System.out.println("后置处理器postProcessAfterInitialization被调用 bean类型=" + bean.getClass() + "bean名字=" + beanName);
        return bean;
    }
}

3.容器类完整代码SunSpringApplicationContext.java
package com.sun.spring.ioc;

import com.sun.spring.annotation.Autowired;
import com.sun.spring.annotation.Component;
import com.sun.spring.annotation.ComponentScan;
import com.sun.spring.annotation.Scope;
import com.sun.spring.processor.BeanPostProcessor;
import com.sun.spring.processor.InitializingBean;
import org.apache.commons.lang.StringUtils;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 类似于Spring原生的ioc容器
 *
 * @author 孙显圣
 * @version 1.0
 */
public class SunSpringApplicationContext {
    //传进来一个配置类的Class对象
    private Class configClass;
    //bean定义字段
    private ConcurrentHashMap<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
    //bean对象字段
    private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();
    //定义一个属性ArrayList来存放后置处理器
    private List<BeanPostProcessor> beanPostProcessors = new ArrayList<>();

    //构造器,接收配置类的class对象
    public SunSpringApplicationContext(Class configClass) throws ClassNotFoundException, InstantiationException, IllegalAccessException {

        //bean定义扫描,并将信息封装到beanDefinitionMap中
        this.beanDefinitionScan(configClass);

        //初始化单例池
        //1.获取所有bean的名字
        Enumeration<String> keys = beanDefinitionMap.keys();
        //2.遍历名字
        while (keys.hasMoreElements()) {
            String beanName = keys.nextElement();
            //3.是单例类型的就创建bean对象并放到单例池中
            BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
            if (beanDefinition.getScope().equals("singleton")) {
                Object bean = createBean(beanDefinition, beanName);
                //4.放到单例池
                singletonObjects.put(beanName, bean);
            }
        }

    }

    public void beanDefinitionScan(Class configClass) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        this.configClass = configClass;
        //一、获取要扫描的包
        //1.首先反射获取类的注解信息
        ComponentScan componentScan = (ComponentScan) this.configClass.getDeclaredAnnotation(ComponentScan.class);
        //2.通过注解来获取要扫描的包的路径
        String path = componentScan.value();
        System.out.println("要扫描的包=" + path);

        //二、得到要扫描包的.class文件对象,从而得到全路径进行反射
        //1.获取类加载器
        ClassLoader classLoader = SunSpringApplicationContext.class.getClassLoader();
        //2.获取要扫描包的真实路径,默认刚开始在根目录下
        path = path.replace(".", "/");
        URL resource = classLoader.getResource(path);
        //3.由该路径创建一个文件对象,可使用resource.getFile()将URL类型转化为String类型
        File file = new File(resource.getFile());
        //4.遍历该文件夹下的所有.class文件对象
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            System.out.println("==================================扫描所有组件==================================");
            for (File f : files) {
                //反射注入容器
                //1.获取所有文件的绝对路径
                String absolutePath = f.getAbsolutePath();
                //只处理class文件
                if (absolutePath.endsWith(".class")) {
                    //2.分割出类名
                    String className = absolutePath.substring(absolutePath.lastIndexOf("\\") + 1,
                            absolutePath.indexOf("."));
                    //3.得到全路径
                    String fullPath = path.replace("/", ".") + "." + className;
                    //4.判断是否需要注入容器,查看有没有自定义的注解Component
                    Class<?> aClass = classLoader.loadClass(fullPath);

                    //如果该类使用了注解Component则说明是一个spring bean
                    if (aClass.isAnnotationPresent(Component.class)) {


                        //后置处理器逻辑
                        //为了方便,将后置处理器放到ArrayList,原生的Spring容器中,对后置处理器还是放到的singletonObjects
                        //判断当前的class对象是否实现了后置处理器的接口
                        if (BeanPostProcessor.class.isAssignableFrom(aClass)) {
                            //如果实现了后置处理器的接口则转换成后置处理器类型
                            BeanPostProcessor beanPostProcessor = (BeanPostProcessor) aClass.newInstance();
                            //添加到ArrayList中
                            beanPostProcessors.add(beanPostProcessor);
                            //后面我们并没有用到单例池中的后置处理器,所以不需要将这个bean定义的信息放到map
                            continue;
                        }

                        System.out.println("这是一个Spring bean=" + aClass);
                        //将Bean的信息封装到BeanDefinition对象中并放入到beanDefinitionMap
                        BeanDefinition beanDefinition = new BeanDefinition();
                        //获取scope注解信息
                        Scope scopeAnnotation = aClass.getDeclaredAnnotation(Scope.class);
                        //只要scopeAnnotation是空的或者他不是空的但是值是空串,则返回singleon,否则就返回value
                        String scope = scopeAnnotation == null || scopeAnnotation.value().equals("") ?
                                "singleton" : scopeAnnotation.value();

                        //封装信息到bean定义字段中
                        beanDefinition.setScope(scope);
                        beanDefinition.setClazz(aClass);

                        //获取Component注解的value值作为beanName
                        Component componentAnnotation = aClass.getDeclaredAnnotation(Component.class);
                        //只要component注解的值是空串就返回类名首字母小写,否则返回这个注解的值
                        String beanName = componentAnnotation.value().equals("") ?
                                StringUtils.uncapitalize(className) : componentAnnotation.value();

                        //封装到beanDefinitionMap中
                        beanDefinitionMap.put(beanName, beanDefinition);


                    } else {
                        System.out.println("这不是一个Spring bean=" + aClass);
                    }

                }
            }

        }

    }

    //根据bean定义对象来创建bean对象
    private Object createBean(BeanDefinition beanDefinition, String beanName) {
        //获取Class对象,反射创建实例
        Class clazz = beanDefinition.getClazz();
        try {
            Object instance = clazz.getDeclaredConstructor().newInstance();
            //进行依赖注入
            //1.遍历所有字段
            for (Field field : clazz.getDeclaredFields()) {
                //2.判断字段中是否有autowired注解
                if (field.isAnnotationPresent(Autowired.class)) {
                    //3.依赖注入
                    String name = field.getName();
                    Object bean = getBean(name);
                    //反射爆破
                    field.setAccessible(true);
                    field.set(instance, bean);
                    System.out.println(instance + "依赖注入完毕!");
                }
            }


            //初始化方法逻辑
            //判断是否要执行Bean的初始化方法
            //存储instance
            Object result = instance;
            //查看这个对象是否实现了InitializingBean接口,instanceof判断是否是某个类型或者某个类型的子类型
            if (instance instanceof InitializingBean) {
                //在初始化方法之前调用后置处理器的before方法,可以对容器的bean进行修改
                for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
                    instance = beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
                }
                //向上转型为接口类型并调用初始化方法
                ((InitializingBean) instance).afterPropertiesSet();
                //在初始化方法之后调用后置处理器的before方法,可以对容器的bean进行修改
                for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
                    instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
                }
            }
            //如果返回的instence是null,则返回之前存贮的结果
            if (instance == null) {
                return result;
            }

            //如果成功则返回这个对象
            return instance;
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    //返回容器中的对象
    public Object getBean(String name) {
        //如果是单例的,则从单例池中获取,如果是多例的则直接创建一个实例返回,名字没在bean定义中则抛出异常
        if (beanDefinitionMap.containsKey(name)) {
            BeanDefinition beanDefinition = beanDefinitionMap.get(name);
            //判断是否是单例
            if ("singleton".equals(beanDefinition.getScope())) {
                //从单例池中获取对象
                return singletonObjects.get(name);
            } else {
                //直接创建对象(多例)
                return createBean(beanDefinition, name);
            }
        } else {
            //name不在bean定义中则抛出异常
            throw new NullPointerException("没有该bean");
        }
    }


}

4.结果展示

image-20240222143316755

4.该阶段完成的任务

  • 实现初始化方法
    • 编写初始化接口,里面有一个default的初始化方法
    • 编写初始化实现类,重写这个初始化方法
    • 在容器的依赖注入后添加初始化逻辑,当这个对象的类型是初始化接口的子类型的时候,就将其转换成接口类型并且调用初始化方法
  • 后置处理器实现
    • 编写一个后置处理器接口,里面有两个方法一个在初始化前调用,一个在初始化后调用
    • 在组件文件夹下编写后置处理器实现类
    • 在容器中beanDefinitionScan方法的扫描组件时添加后置处理器逻辑,如果该组件实现了后置处理器接口,则转换成后置处理器类型,并且放到ArrayList中方便查找
    • 在容器中的createBean方法增加后置处理器逻辑,在初始化方法之前和之后遍历存储后置处理器的ArrayList并分别执行方法

阶段5—实现AOP机制&Spring底层机制总结

1.实现AOP机制

1.原理分析

image-20240222151512245

2.代码实现
1.文件目录

image-20240222164154334

2.编写接口SmartAnimalable.java
package com.sun.spring.component;

/**
 * @author 孙显圣
 * @version 1.0
 */
public interface SmartAnimalable {
    float getSum(float i, float j);
    float getSub(float i, float j);
}

2.编写实现类SmartDog.java
package com.sun.spring.component;

import com.sun.spring.annotation.Component;
import com.sun.spring.processor.InitializingBean;

/**
 * @author 孙显圣
 * @version 1.0
 */
@Component(value = "smartDog")
public class SmartDog implements SmartAnimalable, InitializingBean {
    public float getSum(float i, float j) {
        float res = i + j;
        System.out.println("SmartDog-getSum=" + res);
        return res;
    }

    public float getSub(float i, float j) {
        float res = i - j;
        System.out.println("SmartDog-getSub=" + res);
        return res;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("smartDog 被初始化!");
    }
}

3.编写切面类SmartAnimalAspect.java
package com.sun.spring.component;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class SmartAnimalAspect {
    public static void showBeginLog() {
        System.out.println("前置通知");
    }
    public static void showSuccessLog() {
        System.out.println("返回通知");
    }
}

4.修改SunBeanPostProcessor.java对SmartDog的getSum方法进行动态代理
package com.sun.spring.component;

import com.sun.spring.annotation.Component;
import com.sun.spring.processor.BeanPostProcessor;

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

/**
 * 后置处理器,实现了自定义的后置处理器的接口
 *
 * @author 孙显圣
 * @version 1.0
 */
//反射创建bean对象
@Component
public class SunBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        System.out.println("\n后置处理器postProcessBeforeInitialization被调用 bean类型=" + bean.getClass() + "bean名字=" + beanName);
        if (bean instanceof Car) {
            System.out.println("后置处理器发现这个类型是Car类型");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        System.out.println("后置处理器postProcessAfterInitialization被调用 bean类型=" + bean.getClass() + "bean名字=" + beanName);
        //实现AOP,返回代理对象
        if ("smartDog".equals(beanName)) {
            //使用jdk的动态代理返回代理对象
            /**
             * ClassLoader loader,
             * Class<?>[] interfaces,
             * InvocationHandler h
             */
            //1.要代理的对象的类加载器
            ClassLoader classLoader = bean.getClass().getClassLoader();

            //2.要代理对象的接口信息

            Class<?>[] interfaces = bean.getClass().getInterfaces();

            //3.代理对象执行的方法,在代理对象执行所有的方法时都会调用
            InvocationHandler invocationHandler = new InvocationHandler() {
                /**
                 * 代理对象执行的方法,在代理对象执行所有的方法时都会调用
                 *
                 * @param proxy 动态代理对象
                 *
                 * @param method 动态代理对象调用的方法
                 *
                 * @param args 方法的参数
                 *
                 * @return 返回method返回的结果
                 * @throws Throwable
                 */
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    //判断是不是getSum方法,如果是,则进行AOP处理
                    Object result = null;
                    if ("getSum".equals(method.getName())) {
                        //前置通知
                        SmartAnimalAspect.showBeginLog();
                        result = method.invoke(bean, args);
                        //返回通知
                        SmartAnimalAspect.showSuccessLog();
                    } else {
                        //如果不是getSum方法则正常执行原来的方法
                        result = method.invoke(bean, args);
                    }
                    return result;
                }
            };
            //返回针对接口的代理对象(可以使用接口类型接收)
            return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
        }
        return bean;
    }
}

5.启动类
package com.sun.spring;

import com.sun.spring.component.MonsterService;
import com.sun.spring.component.SmartAnimalable;
import com.sun.spring.ioc.SunSpringApplicationContext;
import com.sun.spring.ioc.SunSpringConfig;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class AppMain {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        SunSpringApplicationContext ioc = new SunSpringApplicationContext(SunSpringConfig.class);

        //单例对象
        Object bean01 = ioc.getBean("monsterDao");

        //测试依赖注入
        MonsterService bean = (MonsterService) ioc.getBean("monsterService");
        System.out.println("==================================测试依赖注入调用方法==================================");
        bean.m1();

        //演示AOP
        System.out.println("==================================测试AOP==================================");
        SmartAnimalable proxy = (SmartAnimalable) ioc.getBean("smartDog");
        proxy.getSub(4,1);
        proxy.getSum(2,4);
    }
}

6.结果展示

image-20240222164835898

3.该阶段完成的任务
  • 编写接口,编写实现类并将实例交给Spring容器管理,编写切面类
  • 后置处理器中进行动态代理操作,这里是对SmartDog类型的getSum方法进行动态代理
    • 首先判断beanName是不是smartDog
    • 如果是则进行动态代理,invoke方法中先判断当前执行的方法是不是getSum
    • 如果是getSum则插入前置通知和返回通知,如果不是则正常执行这个方法

2.Spring底层机制总结

1.bean的生命周期
  • 反射创建bean对象
  • 依赖注入
  • 初始化bean
  • getBean
  • 销毁bean
2.Spring容器的执行流程
  • 获取容器对象
  • 读取配置文件,得到要扫描的包
  • 扫描包下的组件,将bean定义信息放到Map中
  • 如果是单例
    • 反射创建bean对象,放到单例池中
    • 依赖注入(调用getBean)
    • 初始化bean
      • 初始化容器前调用后置处理器的before方法
      • 初始化容器之后调用后置处理器的after方法
  • 如果是多例
    • 在这个阶段什么都不做
  • getBean阶段
    • 如果是单例
      • 从单例池中获取bean对象
    • 如果是多例
      • 反射创建bean对象
      • 依赖注入(调用getBean)
      • 初始化bean
        • 初始化容器前调用后置处理器的before方法
        • 初始化容器之后调用后置处理器的after方法
      • 得到bean对象
  • 销毁bean
3.动态代理和AOP的区别
  • 动态代理:针对的是某个对象所有方法
  • AOP:针对的是某些类型所有对象具体方法
4.关于后置处理器 + 动态代理的理解
  • 后置处理器作用于Spring容器中所有类型,所有对象的初始化方法
  • getBean得到的就是后置处理器返回的bean
  • 当进入到后置处理器的时候
    • 获取切面类的所有信息
    • 将切入表达式与当前bean对象进行对比,只要类型匹配就进行动态代理
    • 使用动态代理进一步筛选要代理的方法,并根据不同的通知执行不同的操作,返回动态代理对象
    • 如果是不需要代理的方法,就不进行额外操作
5.AOP的使用方式
  • 编写接口,接口对象(注解)(用于展示AOP的效果,因为没有对象)
  • 编写切面类(注解),切面对象(注解)
  • 通知 + 切点
  • 配置beans.xnl
    • 普通注解扫描
    • 开启AOP注解
  • 具体使用
    • 获取针对接口类型的代理对象(通过id或者接口类型获取)
    • 使用代理对象调用接口的方法
  • 四种通知
    • 前置通知
    • 返回通知
    • 异常通知
    • 后置通知

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue+OpenLayers7入门到实战,OpenLayers加载GeoJson数据并叠加GeoJson中的要素到地图上

返回《Vue+OpenLayers7》专栏目录:Vue+OpenLayers7入门到实战 前言 本章介绍如何使用OpenLayers7在地图上加载GeoJson数据并叠加GeoJson中的要素到OpenLayers矢量图层上。 GeoJson数据格式可以参考博主另一篇文章《GIS开发入门,GeoJSON是什么?GeoJSON格式标准介绍》,那么…

TLV61048非同步升压BOOST转换器输入电压2.6-5.5V输出电流4A输出电压最高15V

推荐原因&#xff1a; 输入电压较低&#xff0c;输出电流可达3.5A SOT23-6封装 批量价格约0.70元 TLV61048引脚 TLV61048引脚功能 7 详细说明 7.1 概述 TLV61048是一款非同步升压转换器&#xff0c;支持高达 15 V 的输出电压和输入范围从 2.61 V 到 5.5 V。该TLV61048集成了…

不用写一行代码,就能让你的公众号华丽变身成AI智能,超详细的攻略来了~

为了让你的公众号华丽变身成AI智能&#xff0c;我们用到了扣子AI&#xff0c;不用写一行代码&#xff0c;只需要三个步骤&#xff1a;创建Bot、关联公众号、发布Bot。 下面我来给你一个个讲解。 首先打开扣子官网&#xff0c;注册并登录&#xff0c;进入主页面之后就可以开始…

DSPy入门:告别指令提示,拥抱编程之旅!

原文&#xff1a;intro-to-dspy-goodbye-prompting-hello-programming 2024 年 2 月 27 日 DSPy框架如何通过用编程和编译代替提示来解决基于LLM的应用程序中的脆弱性问题。 目前&#xff0c;使用大型语言模型(LLMs)构建应用程序不仅复杂而且脆弱。典型的pipelines通常使用pr…

解决“找不到MSVCP120.dll”或“MSVCP120.dll丢失”的错误方法

在计算机使用过程中&#xff0c;遇到诸如“找不到MSVCP120.dll”或“MSVCP120.dll丢失”的错误提示并不罕见。这类问题往往会导致某些应用程序无法正常运行&#xff0c;给用户带来困扰。本文旨在详细阐述MSVCP120.dll文件的重要性、其丢失的可能原因&#xff0c;以及解决方法&a…

nginx开启basic认证

basic认证也叫做http基本认证&#xff0c;防止恶意访问 首先用在线网站生成一个叫做htpasswd的账号密码文件。 将生成结果复制到/etc/nginx/htpasswd文件中 在server的location中配置 server { listen 80; server_name a.com;location / { root html;index index.…

2001-2021年上市公司制造业智能制造词频统计数据

2001-2021年上市公司制造业智能制造词频统计数据 1、时间&#xff1a;2001-2021年 2、来源&#xff1a;上市公司年报 3、指标&#xff1a;年份、股票代码、行业名称、行业代码、所属省份、所属城市、智能制造词频、智能制造占比(%) 4、范围&#xff1a;上市公司 5、样本量…

基于TSM模块的打架斗殴识别技术

目 录 1 引言.... 4 1.1 研究背景与意义.... 4 1.2 研究现状综述.... 5 1.3 研究内容.... 6 1.3.1 图像预处理的优化.... 6 1.3.2 TSM模块的应用.... 6 1.3.3 视频分类的设计与实现.... 6 2 关键技术与方法.... 8 2.1 TSM算法与模型选择.... 8 2.1.1 TSM算法原理.... 8 2.1.2 …

深度学习-数据预处理

目录 创建一个人工数据集处理缺失的数据插入对inputs中的类别值或离散值&#xff0c;将NaN视为一个类别对inputs和outputs中的数值类型转换为张量格式 创建一个人工数据集 import os import pandas as pd os.makedirs(os.path.join(.., data), exist_okTrue) data_file os.p…

基于Vue+ElementPlus自定义带历史记录的搜索框组件

前言 基于Vue2.5ElementPlus实现的一个自定义带历史记录的搜索框组件 效果如图&#xff1a; 基本样式&#xff1a; 获取焦点后&#xff1a; 这里的历史记录默认最大存储10条&#xff0c;同时右侧的清空按钮可以清空所有历史记录。 同时搜索记录也支持点击搜索&#xff0c;按…

.NET(C#)连接达梦数据库GUID字段被自动加横线的修复方法

因信创的原因项目需要兼容达梦数据库&#xff0c;今天遇到个比较坑爹的问题&#xff0c;简单记录下解决方案。 数据库存的是这样&#xff1a; 通过DataAdapter.Fill拿出来以后变成了这样 纳尼&#xff1f;谁让你加上这些横杠的&#xff1f;&#xff08;掀桌&#xff09;导致了…

100个实用电气知识

在当今社会&#xff0c;电力作为日常生活和工作中不可或缺的能源&#xff0c;扮演着越来越重要的角色。为了更好地利用电力资源&#xff0c;了解电气知识成为了越来越多人的需求。在电气领域&#xff0c;有很多实用的知识&#xff0c;这些知识对于从事电气工作的人来说是非常重…

Linux系统安全:从面临的攻击和风险到安全加固、安全维护策略(文末有福利)

1. Linux面临的攻击与风险 1.1. Linux系统架构 Linux系统架构解读&#xff1a; 用户之间隔离内核态与用户态之间隔离用户进程一般以低权限用户运行系统服务一般以特权服务运行用户态通过系统调用进入内核态内核对系统资源进行管理和分配 1.2. Linux系统常见安全威胁 1.2.1.…

OSPF认证方式,ISIS简介,ISIS路由器类型

OSPF&#xff1a;转发&#xff0c;泛洪&#xff0c;丢弃

Docker搭建代码托管Gitlab

文章目录 一、简介二、Docker部署三、管理员使用四、用户使用五、用户客户端 一、简介 GitLab是一个基于Git的代码托管和协作平台&#xff0c;类似于GitHub。 它提供了一个完整的工具集&#xff0c;包括代码仓库管理、问题跟踪、CI/CD集成、代码审查等功能。 GitLab的开源版本…

Go语言并发赋值的安全性

struct并发赋值 type Test struct {X intY int }func main() {var g Testfor i : 0; i < 1000000; i {var wg sync.WaitGroup// 协程 1wg.Add(1)go func() {defer wg.Done()g Test{1, 2}}()// 协程 2wg.Add(1)go func() {defer wg.Done()g Test{3, 4}}()wg.Wait()// 赋值…

2024新算法角蜥优化算法(HLOA)和经典灰狼优化器(GWO)进行无人机三维路径规划设计实验

简介&#xff1a; 2024新算法角蜥优化算法&#xff08;HLOA&#xff09;和经典灰狼优化器&#xff08;GWO&#xff09;进行无人机三维路径规划设计实验。 无人机三维路径规划的重要意义在于确保飞行安全、优化飞行路线以节省时间和能源消耗&#xff0c;并使无人机能够适应复杂…

国内首个48小时大模型极限挑战赛落幕,四位“天才程序员”共同夺冠

4月21日晚&#xff0c;第四届ATEC科技精英赛&#xff08;ATEC2023&#xff09;线下赛落幕。本届赛事以大模型为技术基座&#xff0c;围绕“科技助老”命题&#xff0c;是国内首个基于真实场景的大模型全链路应用竞赛。ATEC2023线下赛采用48小时极限挑战的形式&#xff0c;来自东…

Ts支持哪些类型和类型运算(上)

目录 1、元组 2、接口&#xff08;interface&#xff09; 3、枚举&#xff08;Enum&#xff09; 4、字面量类型 5、keyof 6、in keyof 7、类型的装饰 静态类型系统 就是把 类型检查从运行时提前到了编译时&#xff0c;所以ts类型系统中的许多类型与js并无区别 例如&am…

概率图模型在机器学习中的应用:贝叶斯网络与马尔可夫随机场

&#x1f9d1; 作者简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…