实现Spring底层机制(三)

news2025/4/11 8:03:53

文章目录

  • 阶段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或者接口类型获取)
    • 使用代理对象调用接口的方法
  • 四种通知
    • 前置通知
    • 返回通知
    • 异常通知
    • 后置通知

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

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

相关文章

BI项目规划第二讲:BI项目实施方案这样设计就够了

在上一篇文章中&#xff0c;我们对BI项目规划中的确定项目范围、组建项目团队两方面进行了详细的解读。 随着项目团队的建立和角色分配的明确&#xff0c;接下来的工作将转向具体的项目实施策略&#xff0c;这是确保项目顺利进行的另一个关键环节。 BI项目实施方案是在项目开…

<前端>Electron-builder为公证后的app打更新信息latest.yml

MacOS下&#xff0c;Electron-builder可以很方便的为测试包app打更新信息&#xff08;latest-mac.yml&#xff09;。 但是&#xff0c;正式发布的时候&#xff0c;不可能用测试包app&#xff0c;因为还没有进行公证。如何为公证的app打latest-mac.yml呢。 其实观察latest-mac.y…

真实世界的密码学(四)

原文&#xff1a;annas-archive.org/md5/655c944001312f47533514408a1a919a 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第十六章&#xff1a;加密何时何地失败 本章涵盖 使用加密时可能遇到的一般问题 遵循烘烤良好的加密的要点 加密从业者的危险和责任 问候…

【IR 论文】Query2doc — 使用 LLM 做 Query Expansion 来提高信息检索能力

论文&#xff1a;Query2doc: Query Expansion with Large Language Models ⭐⭐⭐⭐⭐ Microsoft Research, EMNLP 2023 文章目录 背景介绍Query2doc 论文速读实现细节实验结果和分析总结分析 背景介绍 信息检索&#xff08;Information Retrieval&#xff0c;IR&#xff09;指…

(5)步态识别论文研读——GaitDAN:基于对抗域适应的跨视角步态识别

GaitDAN: Cross-view Gait Recognition via Adversarial Domain Adaptation | IEEE Journals & Magazine | IEEE Xplore GaitDAN: Cross-view Gait Recognition via Adversarial Domain Adaptation 基于对抗与适应 摘要&#xff1a;视角变化导致步态外观存在显着差异。因…

虚假新闻检测——Adapting Fake News Detection to the Era of Large Language Models

论文地址&#xff1a;https://arxiv.org/abs/2311.04917 1.概论 尽管大量的研究致力于虚假新闻检测&#xff0c;这些研究普遍存在两大局限性&#xff1a;其一&#xff0c;它们往往默认所有新闻文本均出自人类之手&#xff0c;忽略了机器深度改写乃至生成的真实新闻日益增长的现…

stabel-TTS

文章目录 model arch model arch github测试网页 text encoder 换成DiT结构&#xff1b;decoder 用flow结构&#xff0c;text 到mel的时长对齐&#xff0c;使用MAS&#xff0c;和Glow-TTS的结构很像【encoder从transformer变成了diffusion】

初识C++ · 类和对象(中)(2)

前言&#xff1a;上篇文章已经介绍了6个默认成员函数中的3个函数&#xff0c;分别是构造函数&#xff0c;析构函数&#xff0c;拷贝构造函数&#xff0c;本文介绍的是后三个&#xff0c;赋值运算符重载&#xff0c;const成员函数&#xff0c;取地址操纵符重载。 目录​​​​​…

【Mysql】用frm和ibd文件恢复mysql表数据

问题 总是遇到mysql服务意外断开之后导致mysql服务无法正常运行的情况&#xff0c;使用Navicat工具查看能够看到里面的库和表&#xff0c;但是无法获取数据记录&#xff0c;提示数据表不存在。 这里记录一下用frm文件和ibd文件手动恢复数据表的过程。 思路 1、frm文件&…

371D - Vessels

思路&#xff1a;用并查集维护&#xff0c;如果当前容器没有满&#xff0c;就指向自己&#xff0c;否则指向下一个容器。 这样就可以快速 find 到下一个没有满的容器&#xff0c;从而模拟询问 1。 代码&#xff1a; void solve(){int n;cin >> n;vector<int>p(n …

刷题之Leetcode242题(超级详细)

242.有效的字母异位词 力扣题目链接(opens new window)https://leetcode.cn/problems/valid-anagram/ 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的字母异位词。 示例 1: 输入: s "anagram", t "nagaram" 输出: true 示例 2…

运维想要不背锅,职责与注意事项,你得仔细看看!

在IT领域&#xff0c;运维人员常常面临着“背锅”的情况。当系统出现故障、服务中断或性能下降时&#xff0c;运维人员往往成为首要责任人。然而&#xff0c;真正的问题并不仅仅是“背锅”&#xff0c;而是在问题发生后如何合理应对和解决。在进行IT运维管理时&#xff0c;我们…

(七)小案例银行家应用程序-申请贷款-some方法和every方法

some方法 ● 我们先回顾一下includes方法 console.log(movements.includes(-130));只要数组中存在-130这个值&#xff0c;就会返回true&#xff0c;否则就会返回flase ● 而some方法只要达成某一个条件就会返回true&#xff0c;否则就返回flase const someMethod movement…

4.23学习总结

一.NIO(一) (一).简介: NIO 是 Java SE 1.4 引入的一组新的 I/O 相关的 API&#xff0c;它提供了非阻塞式 I/O、选择器、通道、缓冲区等新的概念和机制。相比与传统的 I/O 多出的 N 不是单纯的 New&#xff0c;更多的是代表了 Non-blocking 非阻塞&#xff0c;NIO具有更高的并…

ABeam×StartUp丨蓝因机器人访问ABeam旗下德硕管理咨询(深圳)新创部门,展开合作交流

近日&#xff0c;深圳蓝因机器人科技有限公司&#xff08;以下简称“蓝因机器人”&#xff09;创始人陈卜铭先生来访ABeam旗下德硕管理咨询&#xff08;深圳&#xff09;有限公司&#xff08;以下简称“ABeam-SZ”&#xff09;&#xff0c;与新创部门展开合作交流。 交流中&am…

测试 mybatis 是否生效【具有增删改查的功能】

一、 1.1按 anl enter 1.2 注意点&#xff1a; test 下 与 上面的名字需保持一致 测试上面的&#xff0c;路径需保持一致&#xff0c;不一致&#xff0c;后期可能会报错。不是相同目录可能会找不到启动类 1.3 写测试 1.4.1 【先】 添加插件 【一键调用一个对象的所有的se…

C++类和对象:赋值重载,const成员,取地址及const取地址操作符重载

文章目录 1.赋值运算符重载1.1运算符重载1.2 赋值运算符重载1.3 前置和后置重载 2.日期类的实现3. const成员函数4 取地址及const取地址操作符重载 上文介绍了前三个默认成员函数&#xff0c;本文会介绍剩下三个&#xff0c; 赋值重载会重点展开。 1.赋值运算符重载 1.1运算符…

双非一战逆天改命,上岸Top3!

这个系列会邀请上岸学长学姐进行经验分享~今天经验分享的同学同样是小马哥上海交大819的全程班学员&#xff0c;双非逆袭上岸&#xff0c;非常厉害&#xff01; 01-前言 个人介绍&#xff1a;本人就读于江苏某双非&#xff0c;绩点3.2&#xff0c;本科期间仅校赛级别奖项。四…

JavaSE内部类

内部类概述 1.内部类的基础 内部类的分类&#xff1a;实例化内部类&#xff0c;静态内部类&#xff0c;局部内部类和匿名内部类 public class OutClass {// 成员位置定义&#xff1a;未被static修饰 --->实例内部类public class InnerClass1{}// 成员位置定义&#xff1a;被…

公园景区伴随音乐系统-公园景区数字IP广播伴随音乐系统建设指南

公园景区伴随音乐系统-公园景区数字IP广播伴随音乐系统建设指南 由北京海特伟业任洪卓发布于2024年4月23日 随着“互联网”被提升为国家战略&#xff0c;传统行业与互联网的深度融合正在如火如荼地展开。在这一大背景下&#xff0c;海特伟业紧跟时代步伐&#xff0c;凭借其深厚…