Spring:IoC,AOP的简单理解与使用

IoC容器

IoC ,Spring全家桶各个功能模块的基础,是创建对象的容器。

IoC概念

控制反转,将对象的创建进行反转,常规情况下对象由开发者手动创建,而使用IoC不再需要创建对象,由IoC容器根据需求自动创建项目所需要的对象。

IoC环境依赖

添加spring-context,即根据spring上下文,自动引入需要的包

<dependency>
  	<groupId>org.springframework</groupId>
  	<artifactId>spring-context</artifactId>
  	<version>6.0.10</version>
</dependency>

配置元数据

在resource中创建spring配置文件,application.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>

实例化一个ioc容器

ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");

使用容器

比如像通过容器获取一个student对象,在application.xml中配置元数据

<bean class="com.test.bean.Student"/>

通过getBean()检索到bean的实例

Student student = context.getBean(Student.class);

也可以通过对象名来获取,下面这行代码表示创建了一个Student对象,名字为student

<bean class="com.test.bean.Student" id="student"/>
Student student = context.getBean("student");

Bean

是什么?

怎么注册和配置?

bean中scope设置的prototype(原型)和singleton(单例)有什么区别?默认是什么模式?

单例模式中对象在什么时候创建的?

lazy-init是什么?作用是什么

depends-on作用?

Scope

Singleton Scope

单例模式,当定义了一个singleton的bean,Spring IoC容器就会给该bean定义的对象创建一个确切的实例,并且这个单一的实例被存储在这种单体bean的缓存中,所有后续的请求和对该bean的引用都将返回缓存中的对象。这意味通过该bean定义的类创建出来的实例只有一个。

在不写scope的情况下默认为 singleton

<bean class="com.test.entity.Student"/>
Student student1 = context.getBean(Student.class);
Student student2 = context.getBean(Student.class);
System.out.println(student1 == student2); // 单例模式下 这两个对象其实是同一个 返回true
Prototype Scope

原型模式,每次对该特定bean的请求都会创建一个新的bean实例。

<bean class="com.test.entity.Student" scope="prototype"/>

依照这样,上述代码应返回false

依赖注入

IoC容器在创建对象时将我们预先给定的属性注入给对象

基于Setter的依赖注入
public class Student {
    String name;
    private Teacher teacher;

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }

    public void setName(String name) {
        this.name = name;
    }
}

在指定 bean 中使用 property标签

<bean name="teacher" class="com.test.entity.ProgramTeacher"/>
<bean class="com.test.entity.Student">
	<property name="teacher" ref="teacher"/>
    <property name="name" value="小明"/>
</bean>
基于构造器的依赖注入
public class Student {
    String name;
    private final Teacher teacher;

    public Student(String name, Teacher teacher) {
        this.name = name;
        this.teacher = teacher;
    }
}

使用 constructor-arg 标签,构造器中有几个参数,就需要几个constructor-arg

<bean name="teacher" class="com.test.entity.ProgramTeacher"/>
<bean class="com.test.entity.Student">
   	<constructor-arg name="teacher" ref="teacher"/>
    <constructor-arg name="name" value="小明"/>
</bean>
警告: Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.test.entity.Student

请记住,要使这一方法开箱即用,你的代码在编译时必须启用debug标志,以便Spring能够从构造函数中查找参数名称。如果你不能或不想用debug标志编译你的代码,你可以使用 @ConstructorProperties注解来明确命名你的构造函数参数。

    @ConstructorProperties({"name", "teacher"})
    public Student(String name, Teacher teacher) {
        this.name = name;
        this.teacher = teacher;
    }

或在pom.xml中添加-parameters参数

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.10.1</version>
                <configuration>
                    <compilerArgs>
                        <arg>-parameters</arg>
                    </compilerArgs>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
</build>
集合类型的特殊支持

如,Map类型

public class Student {
    private Map<String, Integer> map;

    public void setMap(Map<String, Integer> map) {
        this.map = map;
    }
}
    <bean class="com.test.entity.Student">
        <property name="map">
            <map>
                <entry key="语文" value="100"/>
                <entry key="数学" value="100"/>
                <entry key="英语" value="100"/>
            </map>
        </property>
    </bean>

或者List类型

public class Student {
    private List<String> list;

    public void setList(List<String> list) {
        this.list = list;
    }
}
<bean name="student" class="com.test.Student">
    <property name="list">
        <list>
            <value>AAA</value>
            <value>BBB</value>
            <value>hello</value>
        </list>
    </property>
</bean>

自动装配

自动装配就是让IoC容器自己去寻找需要填入的值,我们只需要将set方法提供好就可以了,这里需要添加autowire属性:

byType 通过类型自动装配

<bean name="programTeacher" class="com.test.entity.ProgramTeacher"/>
<bean class="com.test.entity.Student" autowire="byType"/>

byName 通过名称自动装配,by的name是按照Setter中set后面的名称

public class Student {
    private Teacher teacher;

    public void setProgramTeacher(Teacher teacher) {
        this.teacher = teacher;
    }
}
<bean name="programTeacher" class="com.test.entity.ProgramTeacher"/>
<bean class="com.test.entity.Student" autowire="byName"/>

constructor 通过构造方法自动装配

生命周期

为bean指定初始化或者销毁方法,便于bean在初始化和销毁时做一些其他事情。

为bean配置初始化,在<bean>元素中添加 init-method

<bean class="com.test.entity.Student" autowire="byName" init-method="init"/>
public class Student {
    public void init() {
        System.out.println("i am init");
    }
}

你可以给 <bean> 元素的 destroy-method 属性分配一个特殊的 (inferred) 值,它指示Spring自动检测特定bean类上的public closeshutdown 方法。(任何实现了 java.lang.AutoCloseablejava.io.Closeable 的类都可以匹配)。你也可以在 <beans> 元素的 default-destroy-method 属性上设置这个特殊的 (inferred) 值,将这个行为应用于整个Bean集合。请注意,这是用Java配置的默认行为。

使用实现了AutoCloseableCloseable的类

public class Main {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        context.close();
    }
}
<bean class="com.test.entity.Student" autowire="byName" destroy-method="destroy"/>

或者在顶层<beans>中添加默认的 default-init-methoddefault-destroy-method,这意味着可以编写你的应用类并使用名为 init() 的初始化回调,而不必为每个Bean定义配置 init-method="init" 属性。当Bean被创建时,Spring IoC容器会调用该方法

<beans default-init-method="init"
       default-destroy-method="destroy"
       ........

</beans>

注意的是,Spring并不管理 prototype Bean的完整生命周期,所以配置的destroy不会被调用.

注解实现IoC

比起内容庞大的xml配置,进行注解开发更加高效。

@Configuration

@Configuration等价于spring的xml配置文件

@Configuration
public class MainConfiguration {
}

与xml方式不同,注解开发通过如下方式实例化一个IoC容器:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfiguration.class);

当配置类有很多时,直接扫描包名,例如我将配置类都放在 com.test.config包下

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.test.config");

@Bean

是XML的<bean/>元素的等价。可以在 @Configuration@Component 注解的类中使用 @Bean 注解,注册为bean的对象默认名为方法名(如下面的student),也可以用 @Bean(value = )或者name来自定义名称。

@Configuration
public class MainConfiguration {
    @Bean
    public Student student() {
        return new Student();
    }
}

@Bean 注解支持指定任意的初始化和销毁回调方法,就像Spring XML在 bean 元素上的 init-methoddestroy-method 属性一样,如下例所示。

public class Student {
    public void init() {}
    
    public void destroy(){}
}

@Configuration
public class MainConfiguration {
    @Bean(name = "test", initMethod = "init", destroyMethod = "destroy")
    public Student student() {
        return new Student();
    }
}

Bean别名

@Bean 注解的 name 属性接受一个 String 数组来实现这一目的。

@Bean({"dataSource", "subsystemA-dataSource", "subsystemB-dataSource"})

@Scope

默认的scope是 singleton,但你可以用 @Scope 注解来覆盖它.

@Configuration
public class MainConfiguration {
    @Bean
    @Scope("prototype")
    public Student student() {
        return new Student();
    }
}

@Import

就像 <import/> 元素在Spring XML文件中被用来帮助模块化配置一样,@Import 注解允许从另一个配置类中加载 @Bean 定义,如下例所示。

@Configuration
public class MainConfiguration {
    @Bean
    public Student student() {
        return new Student();
    }
}
@Configuration
@Import(MainConfiguration.class)
public class ChildConfig {
    @Bean
    public ArtStudent artStudent() {
        return new ArtStudent();
    }
}

现在,在实例化上下文时不需要同时指定 MainConfiguration.classChildConfig.class,而只需要明确提供 ChildConfig,正如下面的例子所示。

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new														AnnotationConfigApplicationContext(ChildConfig.class);
        ArtStudent artStudent = context.getBean(ArtStudent.class);
        Student student = context.getBean(Student.class);
    }

@Component

在需要注册为Bean的类上添加@Component注解来将一个类进行注册

@Component
public class SportStudent extends Student{
    private String name;
    public void setName(String name) {
        this.name = name;
    }
}
@Componentscan

同时需要添加@ComponentScan自动扫描来告诉Spring,它需要在哪些包中查找我们提供的@Component声明的Bean。

@Configuration
@ComponentScan("com.test.entity")
public class MainConfiguration {
    @Bean
    public Student student() {
        return new Student();
    }

    public SportStudent sportStudent() {
        return new SportStudent();
    }
}

@Autowired

自动装载

AOP

Aspect Oriented Programming,即面向切面编程。本质就是一个动态代理,让我们把一些常用功能如权限检查、日志、事务等,从每个业务方法中剥离出来。

什么是面向切面呢?就好比将三个西瓜横切一刀,将三个切面抽象为一个对象,对这个对象进行编程(比如输出一个日志),这样输出日志就会在三个切面都执行。

在这里插入图片描述

相关概念

  • Join point(切入点):目标方法和切面的连接点。切面通常通过切入点来获取目标方法的参数,返回值等。
  • Adive(通知):描述切面何时执行以及如何执行增强处理。advice类型包括:before,after,afterReturing,around等。
  • Aspect(切面):通知和切点的结合

引入AOP标签

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

XML配置AOP

public class Student {
    public void study() {
        System.out.println("好好学习");
    }
}

StudentAOP

public class StudentAOP {
    public void afterStudy() {
        System.out.println("我是后置方法");
    }
}

application.xml,在<aop:config/>声明一个<aop:pointcut/>,即切入点,切入点由

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    <bean class="com.test.entity.Student"/>
    <bean id="studentAOP" class="com.test.entity.StudentAOP"/>

    <aop:config>
        <aop:pointcut id="test" expression="execution(public void com.test.entity.Student.study())"/>
        <aop:aspect ref="studentAOP">
            <aop:after method="afterStudy" pointcut-ref="test"/>
        </aop:aspect>
    </aop:config>
</beans>

使用接口实现AOP

在方法执行之前或之后去调用我们实现的接口,首先讲类实现Advice接口,比如方法执行之前的MethodBeforeAdvice,方法执行之后的AfterReturningAdvice。例如

public class AopTest implements MethodBeforeAdvice, AfterReturningAdvice {

    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("我是方法执行之前");
    }

    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("我是方法执行之后");
    }
}

接着在Spring的xml配置文件中,在<aop:config/>标签下使用<aop:advisor/>

<bean name="test" class="com.test.aop.AopTest"/>

<aop:config>
        <aop:pointcut id="stu" expression="execution(* com.test.bean.Student.say(String))"/>
        <aop:advisor advice-ref="test" pointcut-ref="stu"/>
    </aop:config>

注解实现AOP

@EnableAspectJAutoProxy

在添加了@Configuration的spring配置类下使用@EnableAspectJAutoProxy,即开启自动生成代理,这个操作由Spring自己完成

@EnableAspectJAutoProxy
@ComponentScans({
        @ComponentScan("com.test.bean"),
        @ComponentScan("com.test.aop")
})
@Configuration
public class MainConfiguration {

    @Bean
    public Card card() {
        return new Card();
    }

    @Bean
    public Student student() {
        return new Student();
    }
}
@Aspect

要使用AOP,还需要在AOP切面类上使用@Aspect,告诉Spring这是一个切面

@Aspect
@Component
public class AopTest {
   @Before("execution(* com.test.bean.Student.say(String))")
   public void before() {
       System.out.println("我是方法执行之前");
   }
}

从上述代码也能看到,要使用advice的几种操作,只需要使用相应的注解,如@Before@After@Around

Advice类型

Before

在切点匹配方法之前执行,可以通过@Before注解在一个切面中声明advice,execution中的字符串是告诉切面应该在何处执行该方法。

execution的使用:首先表示目标方法的访问范围和返回类型,然后是目标方法的包路径,括号中表示参数类型,例如

execution(public int com.test.bean.CalImpl.*(int, int))

也可以通配

execution(* com.test.bean.CalImpl.*(..))
AfterReturning

当一个匹配的方法执行正常返回带参数时,After returning advice 运行。你可以通过使用 @AfterReturning 注解来声明它,通过参数returning来绑定目标方法的返回结果

@AfterReturning(value = "execution(public int com.test.bean.CalImpl.*(..))", returning = "result")
public void afterReturning(JoinPoint joinPoint, Object result) {
        System.out.println(joinPoint.getSignature().getName() + "方法的结果" + result);
    }
After

当一个匹配的方法执行退出时,After (finally) advice 会运行。它是通过使用 @After 注解来声明的。After advice必须准备好处理正常和异常的返回条件。它通常被用于释放资源和类似的目的。

Around

@Around可以决定是否执行目标方法

AOP实现流程

在这里插入图片描述

SpringEL表达式

简单使用

创建一个SpEL

ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'Hello World'"); // ''表示字符串
String message = (String) exp.getValue();

SpEL支持广泛的功能,如调用方法、访问属性和调用构造函数。

Expression expression = parser.parseExpression("'hello world'.toUpperCase()");

访问对象的属性,前提需要实现get方法

AnnotationConfigApplicationContext context = new                                                          	               AnnotationConfigApplicationContext(MainConfiguration.class);
Student student = context.getBean(Student.class);

ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("name");
String message =(String) expression.getValue(student);

调用表达式的setValues()方法来设定属性的值

Expression expression = parser.parseExpression("name");
expression.setValue(student, "小明");

使用构造函数,如调用String的构造函数

Expression expression = parser.parseExpression("new String('hello world')");

集合类的使用

@Component
public class Student {
    public Map<String, String> map = Map.of("test", "this is test");
    public List<Integer> list = List.of(1,2,3,4);
}

Map映射,通过Map[key]来取出value

Expression expression = parser.parseExpression("map['test']");
String message = (String) expression.getValue(student);

对于List,数组等,可以直接使用[index]

Expression expression = parser.parseExpression("list[2]");
Integer number = (Integer) expression.getValue(student);
.?运算符

.? 运算符通过条件来获取集合元素,例如

@Component
public class Student {
    public List<Exam> list = List.of(new Clazz("操作系统", 80));
    
    public record Exam(String name, int score) {

   	}
}

获取name为操作系统的集合元素:

Expression expression = parser.parseExpression("list.?[name == '操作系统']");
.!运算符

.! 运算符将需要的集合元素属性拿出来单独组成一个集合,例如

@Component
public class Student {
    public List<Exam> list = List.of(new Exam("操作系统", 100), new Exam("计算机组成原理", 75), new Exam("数据结构", 100));
    public record Exam(String name, int score) {

   }
}

我希望把所有的Exam的name取出来:

Expression expression = parser.parseExpression("list.![name]");

Spring高级特性

任务调度

定时任务

定时任务就是指定某个时间去执行任务,在Spring中,定时任务是全局性的,需要在配置类上添加@EnableScheduling

@EnableScheduling
@Configuration
public class MainConfiguration {
    @Bean
    public Student student() {
        return new Student();
    }
}
@Scheduled

方法级注解,设定任务执行的时间,参数如下:

  • fixedDelay:在上一次定时任务执行完之后,间隔多久继续执行。单位毫秒
  • fixedRate:无论上一次定时任务有没有执行完成,两次任务之间的时间间隔。单位毫秒
  • cron:如果嫌上面两个不够灵活,你还可以使用cron表达式来指定任务计划。

如例子:每隔两秒执行一次

@EnableScheduling
@Configuration
public class MainConfiguration {
    @Scheduled(fixedRate = 2000)
//    @Scheduled(fixedDelay = 2000)
//    @Scheduled(cron = "*/2 * * * * *")
    public void task() {
        System.out.println("hello world " + new Date());
    }
}
cron表达式

格式 * * * * * * ,分别代表 秒 分 时 天 月 星期

如每秒,则为 */2 * * * * *

一看就懂:cron 表达式_cron表达式-CSDN博客

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

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

相关文章

2023年【上海市安全员C3证】考试内容及上海市安全员C3证复审考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 上海市安全员C3证考试内容是安全生产模拟考试一点通总题库中生成的一套上海市安全员C3证复审考试&#xff0c;安全生产模拟考试一点通上上海市安全员C3证作业手机同步练习。2023年【上海市安全员C3证】考试内容及上海…

MyCAT2的主从配置

http://t.csdnimg.cn/KzwDy&#xff08;mysql主从搭建&#xff09; 前提&#xff0c;先搭建好MySQL的主从配置&#xff0c;登录MyCAT 2在MyCAT2里面操作&#xff0c;也就是连接8066这个端口。 一、创建数据源 ​​​​​​​1.创建数据源 添加读写的数据源 /* mycat:createD…

U4_1:图论之DFS/BFS/TS/Scc

文章目录 一、图的基本概念二、广度优先搜索&#xff08;BFS&#xff09;记录伪代码时间复杂度流程应用 三、深度优先搜索&#xff08;DFS&#xff09;记录伪代码时间复杂度流程时间戳结构BFS和DFS比较 四、拓扑排序一些概念有向图作用拓扑排序 分析伪代码时间复杂度彩蛋 五、强…

阿里云oss存储文件上传功能实现(保姆级教程)

先登录&#xff1a; 点击进入控制台 点击左上角导航栏按钮 搜索oss&#xff0c;点击进入 进入之后点击立即开通oss按钮&#xff0c;开通之后点击下图立即创建&#xff0c;弹出创建Bucket 填上Bucket名称&#xff0c;读写权限改为公共读。其他不变点击确定创建&#xff0c;完成…

uniapp、微信小程序返回上页面刷新数据

目录 前言&#xff1a; 方法1&#xff1a; 方法2&#xff1a; 方法3&#xff1a; 前言&#xff1a; 返回上页面刷新数据这个功能主要用于在当前页面点击跳转到另一个页面之后&#xff0c;在另一个页面对数据进行了操作&#xff0c;比如&#xff1a;阅读量&#xff0c;然后返…

计算机组成原理-主存储器与CPU的连接

文章目录 知识总览单块存储芯片与CPU的连接位扩展&#xff08;存储字的位数&#xff09;字扩展&#xff08;存储字数&#xff09;关于线选法和片选法字位同时扩展总结补充&#xff1a;译码器 知识总览 单块存储芯片与CPU的连接 数据总线&#xff0c;地址总线&#xff0c;片选线…

Web 自动化神器 TestCafe—页面基本操作篇

前 言 Testcafe是基于node.js的框架&#xff0c;以操作简洁著称&#xff0c;是web自动化的神器 今天主要给大家介绍一下testcafe这个框架和页面元素交互的方法。 一、互动要求 使用 TestCafe 与元素进行交互操作&#xff0c;元素需满足以下条件&#xff1a;☟ 元素在 body 页…

迅为RK3568开发板学习之Linux驱动篇第十三期输入子系统

驱动视频全新升级&#xff0c;并持续更新~更全&#xff0c;思路更科学&#xff0c;入门更简单。 迅为基于iTOP-RK3568开发板进行讲解&#xff0c;本次更新内容为第十三期&#xff0c;主要讲解输入子系统&#xff0c;共计24 讲。 关注B站&#xff1a;北京迅为电子&#xff0c;在…

Parallel Diffusion Models of Operator and Image for Blind Inverse Problems

盲逆问题算子和图像的并行扩散模型 论文链接&#xff1a;https://arxiv.org/abs/2211.10656 项目链接&#xff1a;https://github.com/BlindDPS/blind-dps Abstract 在正向算子已知的情况下(即非盲)&#xff0c;基于扩散模型的逆问题求解器已经展示了最先进的性能。然而&…

OSG文字-各种文字效果(边框、阴影及颜色倾斜)示例(2)

各种文字效果(边框、阴影及颜色倾斜)示例 各种文字效果(边框、阴影及颜色倾斜)示例的代码如程序清单9-2所示&#xff1a; 1. /* 各种文字效果(边框、阴影及颜色倾斜)示例 */ 2. osg::ref_ptr<osg::Camera> createAllKindText(const string &strDataFolder) 3. {…

华为云cce中环境变量的使用

如上图&#xff0c;cce中的环境变量可配置。 配置后的这些参数怎么用呢&#xff1f; 我们可以在docker打包前在springboot的配置文件中配置&#xff0c;cce在启动的时候会调用环境变量中的设置。 如上图&#xff0c;配置的东西以key值标记&#xff0c;冒号后面的是默认配置项…

YOLO改进系列之注意力机制(GatherExcite模型介绍)

模型结构 尽管在卷积神经网络&#xff08;CNN&#xff09;中使用自底向上的局部运算符可以很好地匹配自然图像的某些统计信息&#xff0c;但它也可能阻止此类模型捕获上下文的远程特征交互。Hu等人提出了一种简单&#xff0c;轻量级的方法&#xff0c;以在CNN中更好地利用上下…

ssm+vue的药店药品信息管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的药店药品信息管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结…

Run Legends将健身运动游戏化,使用户保持健康并了解Web3游戏

最近&#xff0c;我们有机会采访Talofa Games的首席执行官兼创始人Jenny Xu&#xff0c;一起讨论游戏开发&#xff0c;Talofa Games是Run Legends这款健身游戏的开发工作室。她已经创作了超过一百款游戏&#xff0c;对于推动游戏的可能性并将她的创造力和叙事技巧带入她最喜爱的…

简单但好用:4种Selenium截图方法了解一下!

前言 我们执行UI自动化操作时&#xff0c;大多数时间都是不在现场的&#xff0c;出现错误时&#xff0c;没有办法第一时间查看到&#xff0c;这时我们可以通过截图当时出错的场景保存下来&#xff0c;后面进行查看报错的原因&#xff0c;Selenium中提供了几种截图的方法&#x…

【Linux学习笔记】基础IO

这里写目录标题 1. 系统文件I/O1.1. 接口介绍1.2. 库函数接口与系统接口的关系 2. 文件描述符fd2.1. 0&1&2文件描述符2.2. 文件描述符的分配规则2.3. 重定向2.4. 重定向系统调用2.5. 进程独立性 3. Linux下一切皆文件4. 缓冲区4.1. 缓冲区的理解4.2. 缓冲区的位置 5. 理…

IDEA-运行测试方法提示Command line is too long

使用IDEA版本 执行时提示 处理方法&#xff1a; 1&#xff0c; 2&#xff0c;

【优秀毕设】基于vue+ssm+springboot的网上购物商城系统设计

摘 要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;网上商城购物系统当然也不能排除在外。网上商城购物系统是以实际运用为开发背景&#xff0c;运用软件工程原理和开发方…

Hadoop-- hdfs

1、HDFS中的三个进程&#xff1a;NameNode&#xff08;NN&#xff09;、DataNode(DN)、SecondNameNode(SNN) 2、NameNode&#xff08;NN&#xff09; 1、作用&#xff1a; 1、接收客户端的一个读、写的服务&#xff0c;在namenode上存储了数据文件和datanode的映射的关系。 …

【封装UI组件库系列】全局样式的定义与重置

封装UI组件库系列第二篇样式​​​​​​​ ​​​​​​&#x1f31f;前言 &#x1f31f;定义全局样式 生成主题色和不同亮度的颜色 ​编辑 中性色及其他变量 &#x1f31f;样式重置 &#x1f31f;总结 ​​​​​​​​​​​​​​&#x1f31f;前言 在前端开发中&…