当前位置: 首页 > news >正文

Spring-bean的生命周期-终篇

阶段8:Bean属性设置阶段

属性设置阶段分为3个小的阶段

  • 实例化后阶段
  • Bean属性赋值前处理
  • Bean属性赋值

实例化后阶段
这里也有spring给我们预留了扩展,就是实现InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法,开发者实现这个接口,重写此方法可以了
源码:

for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {return;}}
}

postProcessAfterInstantiation 方法返回false的时候,后续的Bean属性赋值前处理、Bean属性赋值都会被跳过了。

spring源码位置:

default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return true;
}

来个案例,先建一个process

/*** @description: 设置赋值前,如果返回false将不会被赋值** 会调用 InstantiationAwareBeanPostProcessor 接口的 postProcessAfterInstantiation 这个方* 法,调用逻辑如下:,* 后续的Bean属性赋值前处理、Bean* 属性赋值都会被跳过了。* @author: stone* @date: Created by 2021/3/25 20:25* @version: 1.0.0* @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.setprop*/
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {/*** 后续的Bean属性赋值前处理、Bean*  属性赋值都会被跳过了。* @param bean* @param beanName* @return* @throws BeansException*/@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
//        System.out.println("调用 MyInstantiationAwareBeanPostProcessor#postProcessAfterInstantiation");if ("pig1".equalsIgnoreCase(beanName)) {return false;}return true;}

再来一个spring bean

package com.shiguiwu.springmybatis.spring.lifecycle.definition;import com.shiguiwu.springmybatis.spring.lifecycle.instance.MyAutowire;
import lombok.Data;/*** @description: 小猪* @author: stone* @date: Created by 2021/3/17 14:08* @version: 1.0.0* @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.definition*/
@Data
public class Pig {private String name;private Integer age;private String description;public Pig() {}@MyAutowirepublic Pig(String name, Integer age) {System.out.println("增强候选注解@MyAutowire !!!!");this.name = name;this.age = age;}public Pig(String name, Integer age, String description) {this.name = name;this.age = age;this.description = description;}
}

测试案例如下:

public class InstancedTests {public static void main(String[] args) {DefaultListableBeanFactory factory = new DefaultListableBeanFactory();factory.addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Pig.class).addPropertyValue("name", "猪八戒").addPropertyValue("age", 30).getBeanDefinition();BeanDefinition beanDefinition1 = BeanDefinitionBuilder.genericBeanDefinition(Pig.class).addPropertyValue("name", "猪悟能").addPropertyValue("age", 35).getBeanDefinition();factory.registerBeanDefinition("pig", beanDefinition);factory.registerBeanDefinition("pig1", beanDefinition1);Arrays.stream(factory.getBeanDefinitionNames()).forEach(s -> System.out.println(factory.getBean(s)));}
}

打印结果

Connected to the target VM, address: '127.0.0.1:52046', transport: 'socket'
20:22:20.387 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'pig'
调用InstantiationAwareBeanPostProcessor #postProcessProperties
Pig(name=猪无能, age=12, description=null)
20:22:20.770 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'pig1'
Pig(name=null, age=null, description=null)
Disconnected from the target VM, address: '127.0.0.1:52046', transport: 'socket'

被指定的bean名称,跳过了属性赋值

Bean属性赋值前阶段
这个阶段,spring照样为开发者预留了干涉spring bean赋值前阶段的操作,这个阶段会调用 InstantiationAwareBeanPostProcessor 接口的postProcessProperties 方法,调
用逻辑:
代码如下:

for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds,bw.getWrappedInstance(), beanName);if (pvsToUse == null) {return;}}pvs = pvsToUse;}
}

从上面可以看出,如果 InstantiationAwareBeanPostProcessor 中的
postProcessProperties 和 postProcessPropertyValues 都返回空的时候,表示这个bean不
需要设置属性,直接返回了,直接进入下一个阶段。

来看一下 postProcessProperties 这个方法的定义:

@Nullable
default PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {return pvs;
}

PropertyValues中保存了bean实例对象中所有属性值的设置,所以我们可以在这个这个方法中对PropertyValues值进行修改

示例代码如下:

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {System.out.println("调用InstantiationAwareBeanPostProcessor #postProcessProperties");if (beanName.equals("pig")) {if (pvs==null) {pvs = new MutablePropertyValues();}if (pvs instanceof MutablePropertyValues) {MutablePropertyValues pv = (MutablePropertyValues) pvs;//偷梁换柱,给属性辅助pv.add("name", "猪无能");pv.add("age", 12);}}return null;
}

Bean属性赋值阶段
这个过程比较简单了,循环处理 PropertyValues 中的属性值信息,通过反射调用set方法将属性的值设置到bean实例中。
PropertyValues中的值是通过bean xml中property元素配置的,或者调用MutablePropertyValues中add方法设置的值。


阶段9:Bean初始化阶段

这个阶段分为5个小的阶段

  • Bean Aware接口回调
  • Bean初始化前操作
  • Bean初始化操作
  • Bean初始化后操作
  • Bean初始化完成操作

Bean Aware接口回调,这里也是spring给我们的扩展
这块的源码:

private void invokeAwareMethods(final String beanName, final Object bean) {if (bean instanceof Aware) {if (bean instanceof BeanNameAware) {((BeanNameAware) bean).setBeanName(beanName);}if (bean instanceof BeanClassLoaderAware) {ClassLoader bcl = getBeanClassLoader();if (bcl != null) {((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);}}if (bean instanceof BeanFactoryAware) {((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);}}
}

如果我们的bean实例实现了上面的接口,会按照下面的顺序依次进行调用:

BeanNameAware:将bean的名称注入进去
BeanClassLoaderAware:将BeanClassLoader注入进去
BeanFactoryAware:将BeanFactory注入进去

来一个实现这三个接口的类:

/*** @description: 三个接口* @author: stone* @date: Created by 2021/3/28 11:54* @version: 1.0.0* @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.init*/
public class MyAware implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware {@Overridepublic void setBeanName(String name) {System.out.println("beanName:" + name);}@Overridepublic void setBeanClassLoader(ClassLoader classLoader) {System.out.println("classLoader:" + classLoader);}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("beanFactory:" + beanFactory);}
}

测试代码:

package com.shiguiwu.springmybatis.spring.lifecycle.init;import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;/*** @description: 9.1初始化-aware接口回调* @author: stone* @date: Created by 2021/3/28 11:51* @version: 1.0.0* @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.init*/
public class AwareTests {public static void main(String[] args) {DefaultListableBeanFactory factory = new DefaultListableBeanFactory();BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(MyAware.class).getBeanDefinition();factory.registerBeanDefinition("myAware", beanDefinition);System.out.println(factory.getBean(MyAware.class));}
}

输出信息

Connected to the target VM, address: '127.0.0.1:55707', transport: 'socket'
22:21:14.221 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'myAware'
beanName:myAware
classLoader:sun.misc.Launcher$AppClassLoader@18b4aac2
beanFactory:org.springframework.beans.factory.support.DefaultListableBeanFactory@6c3f5566: defining beans [myAware]; root of factory hierarchy
com.shiguiwu.springmybatis.spring.lifecycle.init.MyAware@71248c21
Disconnected from the target VM, address: '127.0.0.1:55707', transport: 'socket'

Bean初始化前操作,spring给开发者的扩展
这个阶段的源码:

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {Object result = existingBean;for (BeanPostProcessor processor : getBeanPostProcessors()) {Object current = processor.postProcessBeforeInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;
}

会调用 BeanPostProcessor的postProcessBeforeInitialization 方法,若返回null,当前方法将结束。
通常称postProcessBeforeInitialization这个方法为:bean初始化前操作。
这个接口有2个实现类,比较重要,画重点:

org.springframework.context.support.ApplicationContextAwareProcessor
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor

ApplicationContextAwareProcessor注入6个Aware接口对象
如果bean实现了下面的接口,在ApplicationContextAwareProcessor#postProcessBeforeInitialization 中会依次调用下面接口中的方法,将 Aware 前缀对应的对象注入到bean实例中。

EnvironmentAware:注入Environment对象
EmbeddedValueResolverAware:注入EmbeddedValueResolver对象
ResourceLoaderAware:注入ResourceLoader对象
ApplicationEventPublisherAware:注入ApplicationEventPublisher对象
MessageSourceAware:注入MessageSource对象
ApplicationContextAware:注入ApplicationContext对象

从名称上可以看出这个类以 ApplicationContext 开头的,说明这个类只能在 ApplicationContext 环境中使用。

CommonAnnotationBeanPostProcessor调用@PostConstruct标注的方法
CommonAnnotationBeanPostProcessor#postProcessBeforeInitialization 中会调用bean中所有标注@PostConstruct注解的方法
整体来个案例

package com.shiguiwu.springmybatis.spring.lifecycle.init;import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.StringValueResolver;import javax.annotation.PostConstruct;/*** @description: 初始化前操作* @author: stone* @date: Created by 2021/3/28 12:06* @version: 1.0.0* @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.init*/
public class BeforeBean implements EnvironmentAware, EmbeddedValueResolverAware,ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware,ApplicationContextAware {@PostConstructpublic void postConstruct1() {System.out.println("postConstruct1");}@PostConstructpublic void postConstruct2() {System.out.println("postConstruct2");}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {System.out.println("applicationContext:" + applicationContext);}@Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {System.out.println("applicationEventPublisher:" + applicationEventPublisher);}@Overridepublic void setEmbeddedValueResolver(StringValueResolver resolver) {System.out.println("resolver:" + resolver);}@Overridepublic void setEnvironment(Environment environment) {System.out.println("environment:" + environment);}@Overridepublic void setMessageSource(MessageSource messageSource) {System.out.println("messageSource:" + messageSource);}@Overridepublic void setResourceLoader(ResourceLoader resourceLoader) {System.out.println("resourceLoader:" + resourceLoader);}
}

测试代码如下:

package com.shiguiwu.springmybatis.spring.lifecycle.init;import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @description: 9.2初始化前* @author: stone* @date: Created by 2021/3/28 12:04* @version: 1.0.0* @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.init*/
public class BeforeInitTests {public static void main(String[] args) {AnnotationConfigApplicationContext factory = new AnnotationConfigApplicationContext();
//        BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(BeforeBean.class).getBeanDefinition();
//        factory.("beforeBean", beanDefinition);factory.register(BeforeBean.class);factory.refresh();System.out.println(factory.getBean(BeforeBean.class));}
}

打印结果

environment:StandardEnvironment {activeProfiles=[], defaultProfiles= ...
resolver:org.springframework.beans.factory.config.EmbeddedValueResolver@3a52dba3
resourceLoader:org.springframework.context.annotation.AnnotationConfigApplicationContext@11438d26, started on Tue Nov 02 22:59:30 CST 2021
applicationEventPublisher:org.springframework.context.annotation.AnnotationConfigApplicationContext@11438d26, started on Tue Nov 02 22:59:30 CST 2021
messageSource:org.springframework.context.annotation.AnnotationConfigApplicationContext@11438d26, started on Tue Nov 02 22:59:30 CST 2021
applicationContext:org.springframework.context.annotation.AnnotationConfigApplicationContext@11438d26, started on Tue Nov 02 22:59:30 CST 2021
postConstruct1
postConstruct2
com.shiguiwu.springmybatis.spring.lifecycle.init.BeforeBean@610f7aa

大家可以去看一下AnnotationConfigApplicationContext的源码,其内部会添加很多
BeanPostProcessor 到 DefaultListableBeanFactory 中。


Bean初始化阶段
2个步骤

  1. 调用InitializingBean接口的afterPropertiesSet方法
  2. 调用定义bean的时候指定的初始化方法
    调用InitializingBean接口的afterPropertiesSet方法
public interface InitializingBean {public void afterPropertiesSet() throws Exception;
}

当我们的bean实现了这个接口的时候,会在这个阶段被调用
调用bean定义的时候指定的初始化方法
方式1:xml方式指定初始化方法

<bean init-method="bean中方法名称"/>

方式2:@Bean的方式指定初始化方法

@Bean(initMethod = "初始化的方法")

方式3:api的方式指定初始化方法

this.beanDefinition.setInitMethodName(methodName);

初始化方法最终会赋值给下面这个字段

org.springframework.beans.factory.support.AbstractBeanDefinition#initMethodName

案例如下:

package com.shiguiwu.springmybatis.spring.lifecycle.init;import org.springframework.beans.factory.InitializingBean;/*** @description: 初始化bean* @author: stone* @date: Created by 2021/3/28 13:04* @version: 1.0.0* @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.init*/
public class InitializeBean implements InitializingBean {public void init() {System.out.println("初始化方法!!!!");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("afterPropertiesSet");}
}

测试代码

package com.shiguiwu.springmybatis.spring.lifecycle.init;import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;/*** @description: 9.3初始化阶段* @author: stone* @date: Created by 2021/3/28 13:02* @version: 1.0.0* @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.init*/
public class InitializeTests {public static void main(String[] args) {DefaultListableBeanFactory factory = new DefaultListableBeanFactory();BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(InitializeBean.class).getBeanDefinition();beanDefinition.setInitMethodName("init");factory.registerBeanDefinition("initializeBean", beanDefinition);System.out.println(factory.getBean(InitializeBean.class));}
}

输出结果

23:09:16.350 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory 
afterPropertiesSet
初始化方法!!!!
com.shiguiwu.springmybatis.spring.lifecycle.init.InitializeBean@221af3c0
'socket'

调用顺序:InitializingBean中的afterPropertiesSet、然后在调用自定义的初始化方法


Bean初始化后阶段

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {Object result = existingBean;Object current;for(Iterator iterator = this.getBeanPostProcessors().iterator(); iterator.hasNext(); result = current) {BeanPostProcessor processor = (BeanPostProcessor)iterator.next();current = processor.postProcessAfterInitialization(result, beanName);if (current == null) {return result;}}return result;
}

调用 BeanPostProcessor接口的postProcessAfterInitialization方法 ,返回null的时候,会中断上面的操作,注意这里也是扩展哦
通常称postProcessAfterInitialization这个方法为:bean初始化后置操作。
来个案例

public class MyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("bean :" + beanName);System.out.println("初始化后》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》");return bean;}
}

测试代码

package com.shiguiwu.springmybatis.spring.lifecycle.init;import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;/*** @description: 9.4初始化后阶段* @author: stone* @date: Created by 2021/3/28 13:07* @version: 1.0.0* @pakeage: com.shiguiwu.springmybatis.spring.lifecycle.init*/
public class AfterInitializeTests {public static void main(String[] args) {DefaultListableBeanFactory factory = new DefaultListableBeanFactory();//叫一个初始化后处理器factory.addBeanPostProcessor(new MyBeanPostProcessor());AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(String.class).addConstructorArgValue( "shiguiwu").getBeanDefinition();AbstractBeanDefinition beanDefinition1 = BeanDefinitionBuilder.genericBeanDefinition(Integer.class).addConstructorArgValue(15).getBeanDefinition();factory.registerBeanDefinition("shiguiwuabc", beanDefinition);factory.registerBeanDefinition("shiguiwuA", beanDefinition1);System.out.println(factory.getBean(String.class));System.out.println(factory.getBean(Integer.class));}
}

输出结果

Connected to the target VM, address: '127.0.0.1:56910', transport: 'socket'
23:20:37.770 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'shiguiwuabc'
bean :shiguiwuabc
初始化后》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
shiguiwu
23:20:38.099 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'shiguiwuA'
bean :shiguiwuA
初始化后》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
15
Disconnected from the target VM, address: '127.0.0.1:56910', transport: 'socket'Process finished with exit code 0

此致,终篇完毕,内容有点,希望能好好消化,接下来就是尾篇。

相关文章:

Spring-bean的生命周期-终篇

阶段8&#xff1a;Bean属性设置阶段 属性设置阶段分为3个小的阶段 实例化后阶段Bean属性赋值前处理Bean属性赋值 实例化后阶段 这里也有spring给我们预留了扩展&#xff0c;就是实现InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法&#xff0c;开发…...

Kotlin 枚举和 when 表达式(六)

导读大纲 1.1 表示和处理选择: Enums和when1.1.1 声明枚举类和枚举常量1.1.2 使用 when 表达式处理枚举类 1.1 表示和处理选择: Enums和when 在本节中,我们将以在 Kotlin 中声明枚举为例,介绍 when 结构 when可以被视为比 Java 中 switch 结构更强大、更常用的替代品 1.1.1 …...

数字范围按位与

优质博文&#xff1a;IT-BLOG-CN 题目 给你两个整数left和right&#xff0c;表示区间[left, right]&#xff0c;返回此区间内所有数字 按位与 的结果&#xff08;包含left、right端点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;left 5, right 7 输出&#xff1a;…...

WebRTC编译后替换libwebrtc.aar时提示找不到libjingle_peerconnection_so.so库

Loading native library: jingle_peerconnection_so 问题原因&#xff1a;编译的时候只编译了armeabi-v7a的版本&#xff0c;但是应用程序是arm64-v8a&#xff0c;所以无法运行 解决方法&#xff1a;更新编译脚本&#xff0c;加上arm64-v8a进行编译 ./tools_webrtc/android/bu…...

Nature Electronics |无感佩戴的纤维基电子皮肤(柔性半导体器件/柔性健康监测/电子皮肤/柔性传感/纤维器件)

英国剑桥大学Yan Yan Shery Huang课题组,在《Nature Electronics 》上发布了一篇题为“Imperceptible augmentation of living systems with organic bioelectronic fibres”的论文,第一作者为王文宇博士(Wenyu Wang),论文内容如下: 一、 摘要 利用电子技术对人类皮肤和…...

深入剖析Docker容器安全:挑战与应对策略

随着容器技术的广泛应用&#xff0c;Docker已成为现代应用开发和部署的核心工具。它通过轻量级虚拟化技术实现应用的隔离与封装&#xff0c;提高了资源利用率。然而&#xff0c;随着Docker的流行&#xff0c;其安全问题也成为关注焦点。容器化技术虽然提供了良好的资源隔离&…...

后端技术打怪升级之路

记录后端技术打怪升级之路&#xff0c;如下是个人总记的主要技术栈&#xff0c;仅供参考&#xff01; 备注&#xff1a; 同名文章一同步发表于个人网站及微信公众号 个人网站 工藤新一的技术小窝...

Leetcode 3296. Minimum Number of Seconds to Make Mountain Height Zero

Leetcode 3296. Minimum Number of Seconds to Make Mountain Height Zero 1. 解题思路2. 代码实现 题目链接&#xff1a;3296. Minimum Number of Seconds to Make Mountain Height Zero 1. 解题思路 这一题的思路的话我们采用的是一个二分法的思路&#xff0c;找到一个最大…...

计算机毕业设计之:基于深度学习的路面检测系统(源码+部署文档+讲解)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…...

测试面试题:接口自动化测试流程?

1、测试用例编写&#xff1a;根据接口的需求和功能&#xff0c;编写相应的测试用例。测试用例应包括正常、边界和异常等各种情况下的测试。 2、准备测试数据&#xff1a;根据测试用例的要求&#xff0c;准备相应的测试数据。数据可以通过手动输入、数据库查询、文件导入等方式进…...

Golang面试题

在Golang(也称为Go语言)工程师的面试中,可能会遇到各种技术性和概念性的问题。 一、基础部分 Golang 中 make 和 new 的区别? 共同点:两者都用于分配内存。不同点: make 专为 slice、map 和 channel 设计,返回初始化后的(非零)值。new 分配内存并返回指向该内存的指针…...

《飞机大战游戏》实训项目(Java GUI实现)(设计模式)(简易)

目录 一、最终实现后&#xff0c;效果如下。 &#xff08;1&#xff09;简单介绍本游戏项目&#xff08;待完善&#xff09; &#xff08;2&#xff09;运行效果图&#xff08;具体大家自己可以试&#xff09; 初始运行情况。 手动更换背景图。 通过子弹攻击敌机&#xff0c;累…...

计算机毕业设计 基于 Hadoop平台的岗位推荐系统 SpringBoot+Vue 前后端分离 附源码 讲解 文档

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…...

【数据结构与算法】LeetCode:二分查找

文章目录 二分查找二分查找搜索插入位置 &#xff08;Hot 100&#xff09;x 的平方根搜索二维矩阵&#xff08;Hot 100&#xff09;在排序数组中查找元素的第一个和最后一个位置 &#xff08;Hot 100&#xff09;搜索旋转排序数组 &#xff08;Hot 100&#xff09;寻找旋转排序…...

专题·大模型安全 | 生成式人工智能的内容安全风险与应对策略

正如一枚硬币的两面&#xff0c;生成式人工智能大模型&#xff08;以下简称“生成式大模型”&#xff09;在助力内容生成的同时也潜藏风险&#xff0c;成为虚假信息传播、数据隐私泄露等问题的温床&#xff0c;加剧了认知域风险。与传统人工智能&#xff08;AI&#xff09;相比…...

CORS跨域+Nginx配置、Apache配置

CORS&#xff08;Cross-Origin Resource Sharing&#xff0c;跨源资源共享&#xff09;是一种机制&#xff0c;它使用额外的HTTP头部来告诉浏览器允许一个网页运行的脚本从不同于它自身来源的服务器上请求资源&#xff08;例如字体、JavaScript、CSS等&#xff09;。这是一种安…...

文件查找和打包压缩【1.7】

文件查找和打包压缩【1.7】 八、文件查找和打包压缩8.1 文件查找8.1.1 locate8.1.2 findfind8.1.2.1 指定搜索目录层级8.1.2.2 先处理文件再处理目录8.1.2.3 根据文件名和inode查找8.1.2.4 根据属主属组查找8.1.2.5 根据文件类型查找8.1.2.6 空文件或目录8.1.2.7 组合条件8.1.2…...

速盾:cdn一般多长时间清理下缓存?

CDN&#xff08;Content Delivery Network&#xff09;是一种网络加速技术&#xff0c;通过将网站的静态资源&#xff08;如图片、视频、CSS、JavaScript等&#xff09;分布到全球各地的服务器节点上&#xff0c;从而提高用户访问这些资源的速度和体验。CDN还具备缓存功能&…...

react hooks--useRef

基本用法 在类组件中获取一个dom元素实例&#xff0c;可以通过React.CreateRef或者回调函数的方式去获取。语法&#xff1a;const refContainer useRef(initialValue);使用场景&#xff1a;在 React 中进行 DOM 操作时&#xff0c;用来获取 DOM作用&#xff1a;返回一个带有 …...

GPT对话知识库——将寄存器中的一位数据读到变量中需要什么步骤?C语言中掩码的作用。

目录 1&#xff0c;问&#xff1a; 1&#xff0c;答&#xff1a; 1. 确定目标寄存器地址 2. 定位目标位 位操作的基本步骤&#xff1a; 3. 示例代码 示例步骤&#xff1a; 4. 详细解释步骤 5. 举例 6. 常见用法 总结 注&#xff1a; C语言中掩码的作用&#xff1a…...

Claude in Excel:原生集成的AI表格协作者

1. 项目概述&#xff1a;这不是插件&#xff0c;是Excel里长出来的AI同事“Claude in Excel”这个标题刚看到时&#xff0c;我下意识点开几个技术社区翻了一圈&#xff0c;发现多数人第一反应是&#xff1a;“又一个AI插件&#xff1f;”——其实完全不是。它根本没走传统Offic…...

Hitboxer:开源SOCD清理工具,3分钟提升游戏操作精准度

Hitboxer&#xff1a;开源SOCD清理工具&#xff0c;3分钟提升游戏操作精准度 【免费下载链接】socd Key remapper for epic gamers 项目地址: https://gitcode.com/gh_mirrors/so/socd 你是否在激烈的游戏对抗中经历过这样的挫败&#xff1a;同时按下左右方向键时角色卡…...

BurpSuite 2025插件开发JDK版本兼容性实战指南

1. 为什么BurpSuite插件开发环境总在JDK版本上翻车&#xff1f;你是不是也经历过&#xff1a;下载好BurpSuite最新版2025.4&#xff0c;兴冲冲打开插件开发文档&#xff0c;照着官方示例写完第一个HelloWorld插件&#xff0c;一编译——java.lang.UnsupportedClassVersionError…...

ROS Noetic实战:从bag包里‘抠’出雷达点云和IMU数据的保姆级教程(Ubuntu 20.04)

ROS Noetic实战&#xff1a;从bag包里提取雷达点云和IMU数据的完整指南&#xff08;Ubuntu 20.04&#xff09;在机器人开发中&#xff0c;ROS bag文件就像是一个装满珍贵数据的宝箱&#xff0c;而雷达点云和IMU数据则是其中最闪亮的宝石。作为一名长期与ROS打交道的开发者&…...

电子商务设计师软考备战:特别篇 - 综合模拟与备考策略

1. 考试形式与内容结构1.1 考试基本信息考试科目与时间基础知识考试&#xff1a;上午9:00-11:30&#xff08;150分钟&#xff09;应用技术考试&#xff1a;下午2:00-4:30&#xff08;150分钟&#xff09;题型与分值分布上午考试&#xff08;基础知识&#xff09;&#xff1a; -…...

Unity事件系统实战:用事件驱动重构你的金币拾取逻辑(告别硬编码)

Unity事件系统实战&#xff1a;用事件驱动重构你的金币拾取逻辑&#xff08;告别硬编码&#xff09;在游戏开发中&#xff0c;我们经常会遇到这样的场景&#xff1a;玩家拾取金币后&#xff0c;需要更新UI、播放音效、解锁成就、保存数据……如果把这些逻辑全部写在金币拾取的代…...

想深耕网络安全行业,这些必备条件缺一不可

网络空间的攻防对抗日益激烈&#xff0c;网络安全已成为企业生存和国家安全的命脉&#xff0c;它负责构筑数字世界的坚固防线&#xff0c;保护核心资产与用户隐私免受侵害。 想要成为一名优秀的网络安全专家&#xff0c;除了敏锐的安全意识和高度的责任感&#xff0c;更需要锤…...

终极崩坏星穹铁道自动化指南:3分钟掌握解放双手的智能游戏伴侣

终极崩坏星穹铁道自动化指南&#xff1a;3分钟掌握解放双手的智能游戏伴侣 【免费下载链接】StarRailAssistant 崩坏&#xff1a;星穹铁道自动化 | 崩坏&#xff1a;星穹铁道自动锄大地 | 崩坏&#xff1a;星穹铁道锄大地 | 自动锄大地 | 基于模拟按键 项目地址: https://git…...

基于BLE模块的低功耗无线遥控器设计与实现

1. 项目概述&#xff1a;基于BLE模块的无线遥控器设计与实现几年前&#xff0c;我在捣鼓智能家居时&#xff0c;一直想找一个低功耗、响应快、又能自己完全掌控的无线遥控方案。市面上的成品要么协议封闭&#xff0c;要么功耗感人&#xff0c;要么延迟高得让人着急。后来&#…...

三分钟快速上手:FanControl让你的电脑风扇从此安静又高效

三分钟快速上手&#xff1a;FanControl让你的电脑风扇从此安静又高效 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trending…...