一文了解Spring提供的几种扩展能力

基于 spring bean 的扩展

1. BeanPostProcessor

spring 提供的针对 bean 的初始化过程时提供的扩展能力,从方法名也很容易看出,提供的两个方法分别是为 bean 对象提供了初始化之前以及初始化之后的扩展能力。

package com.wyl.conf;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;@Component
public class MyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);}
}

2. InstantiationAwareBeanPostProcessor

package com.wyl.conf;import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {// 相当于new这个bean对象之前return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);}@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {// 相当于new这个bean对象之后return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);}@Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {// 在注入bean对象属性时调用,@Autowired注解就是基于此方法实现的return InstantiationAwareBeanPostProcessor.super.postProcessProperties(pvs, bean, beanName);}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {// 初始化这个bean对象,被spring注入上下文中之前return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {// 初始化这个bean对象,被spring注入上下文中之后return InstantiationAwareBeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);}
}

3. InitializingBean

package com.wyl.conf;import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;@Component
public class MyInitializing implements InitializingBean {@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("===MyInitializing===");}
}

4. 初始化器(ApplicationContextInitializer)

ConfigurableEnvironment 中注册一些 property sources 或获取 getBeanFactory 来访问容器中的 bean

package com.wyl.initializer;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;public class MyInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {@Overridepublic void initialize(ConfigurableApplicationContext applicationContext) {// environmentConfigurableEnvironment environment = applicationContext.getEnvironment();MutablePropertySources propertySources = environment.getPropertySources();String[] activeProfiles = environment.getActiveProfiles();// beanFactoryapplicationContext.getBeanFactory().addBeanPostProcessor(new BeanPostProcessor() {@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);}});}
}

同样可通过 spring.factories 方式进行注册

org.springframework.context.ApplicationContextInitializer=\
com.wyl.initializer.MyInitializer

5. BeanFactoryPostProcessor

package com.wyl.conf;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {System.out.println("MyBeanFactoryPostProcessor---postProcessBeanFactory");}
}

基于 spring boot 的扩展

1. 监听器(SpringApplicationRunListener)

这是针对 SpringApplication.run 方法执行时提供的一种监听能力,可以在服务启动的多个阶段进行控制。

package com.wyl.listener;import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;public class MyListener implements SpringApplicationRunListener {public MyListener(SpringApplication application, String[] args) {}@Overridepublic void starting(ConfigurableBootstrapContext bootstrapContext) {System.out.println("P1---staring");SpringApplicationRunListener.super.starting(bootstrapContext);}@Overridepublic void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {System.out.println("P2---environmentPrepared");SpringApplicationRunListener.super.environmentPrepared(bootstrapContext, environment);}@Overridepublic void contextPrepared(ConfigurableApplicationContext context) {System.out.println("P3---contextPrepared");SpringApplicationRunListener.super.contextPrepared(context);}@Overridepublic void contextLoaded(ConfigurableApplicationContext context) {System.out.println("P4---contextLoaded");SpringApplicationRunListener.super.contextLoaded(context);}@Overridepublic void started(ConfigurableApplicationContext context) {System.out.println("P5---started");SpringApplicationRunListener.super.started(context);}@Overridepublic void running(ConfigurableApplicationContext context) {System.out.println("P6---running");SpringApplicationRunListener.super.running(context);}@Overridepublic void failed(ConfigurableApplicationContext context, Throwable exception) {System.out.println("failed");SpringApplicationRunListener.super.failed(context, exception);}
}

直接通过启动日志的输出位置可直观的看到每个方法的具体扩展点位置。

P1---staring
P2---environmentPrepared.   ____          _            __ _ _/\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )___ | '_ | '_| | '_ / _` | \ \ \ \\/  ___)| |_)| | | | | || (_| |  ) ) ) )'  |____| .__|_| |_|_| |___, | / / / /=========|_|==============|___/=/_/_/_/:: Spring Boot ::                (v2.4.2)P3---contextPrepared
2023-02-16 18:45:11.748  INFO 12108 --- [           main] com.wyl.MyApplication                    : Starting MyApplication using Java 17.0.13 on DESKTOP-6O879NM with PID 12108 (D:\learn\hodgepodge\hodgepodge\my-springboot\target\classes started by 26352 in D:\learn\hodgepodge)
2023-02-16 18:45:11.750  INFO 12108 --- [           main] com.wyl.MyApplication                    : No active profile set, falling back to default profiles: default
P4---contextLoaded
2023-02-16 18:45:12.437  INFO 12108 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2023-02-16 18:45:12.443  INFO 12108 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2023-02-16 18:45:12.443  INFO 12108 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.41]
2023-02-16 18:45:12.495  INFO 12108 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-02-16 18:45:12.495  INFO 12108 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 705 ms
2023-02-16 18:45:12.660  INFO 12108 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2023-02-16 18:45:12.721  INFO 12108 --- [           main] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page template: index
2023-02-16 18:45:12.837  INFO 12108 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2023-02-16 18:45:12.844  INFO 12108 --- [           main] com.wyl.MyApplication                    : Started MyApplication in 1.333 seconds (JVM running for 1.799)
P5---started
P6---running

通过写spring.factories 文件的方式注入即可

org.springframework.boot.SpringApplicationRunListener=\
com.wyl.listener.MyListener

2. Runner

也是用于在启动完成后再执行的代码,并且它可以方便的获取启动参数

package com.wyl.runner;import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;@Component
public class MyRunner implements ApplicationRunner {@Overridepublic void run(ApplicationArguments args) throws Exception {System.out.println("myRunner");for (String nonOptionArg : args.getNonOptionArgs()) {System.out.println(nonOptionArg);}}
}

在这里插入图片描述

P1---staring
P2---environmentPrepared.   ____          _            __ _ _/\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )___ | '_ | '_| | '_ / _` | \ \ \ \\/  ___)| |_)| | | | | || (_| |  ) ) ) )'  |____| .__|_| |_|_| |___, | / / / /=========|_|==============|___/=/_/_/_/:: Spring Boot ::                (v2.4.2)P3---contextPrepared
2023-02-16 18:45:11.748  INFO 12108 --- [           main] com.wyl.MyApplication                    : Starting MyApplication using Java 17.0.13 on DESKTOP-6O879NM with PID 12108 (D:\learn\hodgepodge\hodgepodge\my-springboot\target\classes started by 26352 in D:\learn\hodgepodge)
2023-02-16 18:45:11.750  INFO 12108 --- [           main] com.wyl.MyApplication                    : No active profile set, falling back to default profiles: default
P4---contextLoaded
2023-02-16 18:45:12.437  INFO 12108 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2023-02-16 18:45:12.443  INFO 12108 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2023-02-16 18:45:12.443  INFO 12108 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.41]
2023-02-16 18:45:12.495  INFO 12108 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-02-16 18:45:12.495  INFO 12108 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 705 ms
2023-02-16 18:45:12.660  INFO 12108 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2023-02-16 18:45:12.721  INFO 12108 --- [           main] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page template: index
2023-02-16 18:45:12.837  INFO 12108 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2023-02-16 18:45:12.844  INFO 12108 --- [           main] com.wyl.MyApplication                    : Started MyApplication in 1.333 seconds (JVM running for 1.799)
P5---started
myRunner
myarguments=ok
P6---running

3. 自定义 starter

新建一个 module

在这里插入图片描述

引入依赖

<dependencies><!-- spring boot --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 工具类 --><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId></dependency></dependencies>

在 starter 中我们可以将计数的方法写在一个 service

定义个 MethodAccessCounterService 接口

package com.wyl.service;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public interface MethodAccessCounterService {void count(HttpServletRequest request, HttpServletResponse response, Object handler);}

具体实现

package com.wyl.service.impl;import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import com.wyl.service.MethodAccessCounterService;
import org.springframework.web.method.HandlerMethod;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class MethodAccessCounterServiceImpl implements MethodAccessCounterService {private final Table<String, String, Integer> counter = HashBasedTable.create();@Overridepublic void count(HttpServletRequest request, HttpServletResponse response, Object handler) {String remoteAddr = request.getRemoteAddr();if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod = (HandlerMethod) handler;String path = handlerMethod.getMethod().getDeclaringClass().getName() + "." + handlerMethod.getMethod().getName();if (counter.contains(path, remoteAddr)) {Integer cnt = counter.get(path, remoteAddr);if (cnt == null) {counter.put(path, remoteAddr, 1);} else {counter.put(path, remoteAddr, cnt + 1);}} else {counter.put(path, remoteAddr, 1);}System.out.println("started提供的方式\t" + remoteAddr + "第" + counter.get(path, remoteAddr) + "次访问:" + path);}}
}

使用自动装配将 MethodAccessCounterServiceImpl 注入到 spring bean 的容器中

在这里插入图片描述

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.wyl.config.MethodAccessCounterConfiguration
package com.wyl.config;import com.wyl.service.MethodAccessCounterService;
import com.wyl.service.impl.MethodAccessCounterServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MethodAccessCounterConfiguration {@Beanpublic MethodAccessCounterService methodAccessCounterService() {return new MethodAccessCounterServiceImpl();}}

再把拦截器配上

package com.wyl.interceptor;import com.wyl.service.MethodAccessCounterService;
import org.springframework.web.servlet.HandlerInterceptor;import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class MethodAccessCounterInterceptor implements HandlerInterceptor {@Resourceprivate MethodAccessCounterService methodAccessCounterService;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {methodAccessCounterService.count(request, response, handler);return true;}
}
package com.wyl.config;import com.wyl.interceptor.MethodAccessCounterInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(methodAccessCounterInterceptor()).addPathPatterns("/**");}@Beanpublic MethodAccessCounterInterceptor methodAccessCounterInterceptor() {return new MethodAccessCounterInterceptor();}}

最后,打个包,给到业务方使用即可!

基于 spring web 的扩展

1. 拦截器(HandlerInterceptor)

包依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency><!-- 工具类 -->
<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId>
</dependency>

新建一个自己的 Interceptor

preHandle 方法处,实现对每个 ip 访问每个方法次数的统计

package com.wyl.interceptor;import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class MethodAccessCounterInterceptor implements HandlerInterceptor {private final Table<String, String, Integer> counter = HashBasedTable.create();@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String remoteAddr = request.getRemoteAddr();if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod = (HandlerMethod) handler;String path = handlerMethod.getMethod().getDeclaringClass().getName() + "." + handlerMethod.getMethod().getName();if (counter.contains(path, remoteAddr)) {Integer cnt = counter.get(path, remoteAddr);if (cnt == null) {counter.put(path, remoteAddr, 1);} else {counter.put(path, remoteAddr, cnt + 1);}} else {counter.put(path, remoteAddr, 1);}System.out.println(remoteAddr + "第" + counter.get(path, remoteAddr) + "次访问:" + path);}return true;}
}

将新建的拦截器添加到拦截器链中

package com.wyl.config;import com.wyl.interceptor.MethodAccessCounterInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MethodAccessCounterInterceptor()).addPathPatterns("/**");}
}

测试方法

@Controller
public class TestController {@RequestMapping("/index")public String index() {return "index";}@RequestMapping("/test")public String test() {return "index";}}

测试结果

分别访问:http://localhost:8080/index 与 http://localhost:8080/test 输出的结果如下:

在这里插入图片描述

目录结构

在这里插入图片描述

基于 spring aop 的扩展

1. aop

引入依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

构建切面,在方式执行之前记录

package com.wyl.aop;import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;@Component
@Aspect
public class MethodAccessCounterAspect {private final Table<String, String, Integer> counter = HashBasedTable.create();@Before("execution(* com.wyl.controller.*.*(..))")public void before(JoinPoint joinPoint) {Object[] args = joinPoint.getArgs();HttpServletRequest request = null;for (Object arg : args) {if (arg instanceof HttpServletRequest) {request = (HttpServletRequest) arg;break;}}if (request != null) {String remoteAddr = request.getRemoteAddr();String path = joinPoint.getSignature().getDeclaringTypeName() + '.' + joinPoint.getSignature().getName();if (counter.contains(path, remoteAddr)) {Integer cnt = counter.get(path, remoteAddr);if (cnt == null) {counter.put(path, remoteAddr, 1);} else {counter.put(path, remoteAddr, cnt + 1);}} else {counter.put(path, remoteAddr, 1);}System.out.println("使用aop方式\t" + remoteAddr + "第" + counter.get(path, remoteAddr) + "次访问:" + path);}}
}

新增一个测试方法

方法中要传入 HttpServletRequest 否则切面上无法获取到请求 IP

@RequestMapping("/aop")
public String aop(HttpServletRequest request) {return "index";
}

访问:http://localhost:8080/aop 结果如下:

在这里插入图片描述

完整时序

服务启动加载时序图

在这里插入图片描述

容器环境外执行

SpringApplicationRunListener 提供了多个接口以供使用,其中 starting 方法是最早的执行,此时几乎还没有做任何事情。

在这里插入图片描述

environmentPrepared

在这里插入图片描述

contextPrepared、contextLoaded 两个方法一前一后都在 prepareContext 方法中被执行

在这里插入图片描述

started、running 一目了然,执行到这两个方法时服务已经启动完成了。

在这里插入图片描述

ApplicationContextInitializer 是在 refreshContext 方法之前执行的

在这里插入图片描述

容器环境内执行

另外几个 InitializingBean、BeanPostProcessor、BeanFactoryPostProcessor、InstantiationAwareBeanPostProcessor、ApplicationContextInitializer 都是在执行 refreshContext 方法时处理,由 org.springframework 包提供。

在这里插入图片描述

Bean 实例化与初始化的入口方法整理

实例化前

BeanFactoryPostProcessor -> postProcessBeanFactory

InstantiationAwareBeanPostProcessor -> postProcessBeforeInstantiation

实例化后

InstantiationAwareBeanPostProcessor -> postProcessAfterInstantiation

InstantiationAwareBeanPostProcessor -> postProcessPropertyValues

初始化前

BeanPostProcessor - > postProcessBeforeInitialization

InstantiationAwareBeanPostProcessor - > postProcessBeforeInitialization

初始化后

InitializingBean -> afterPropertiesSet

BeanPostProcessor - > postProcessAfterInitialization

InstantiationAwareBeanPostProcessor - > postProcessAfterInitialization

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

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

相关文章

【隐私计算大模型】联邦深度学习之拆分学习Split learning原理及安全风险、应对措施以及在大模型联合训练中的应用案例

Tips&#xff1a;在两方场景下&#xff0c;设计的安全算法&#xff0c;如果存在信息不对等性&#xff0c;那么信息获得更多的一方可以有概率对另一方实施安全性攻击。 1. 拆分学习原理 本文介绍了一种适用于隐私计算场景的深度学习实现方案——拆分学习&#xff0c;又称分割…

Linux 下进程基本概念与状态

文章目录 一、进程的定义二、 描述进程-PCBtask_ struct内容分类 三、 进程状态 一、进程的定义 狭义定义&#xff1a;进程是正在运行的程序的实例&#xff08;an instance of a computer program that is being executed&#xff09;。广义定义&#xff1a;进程是一个具有一定…

k8s1.31版本最新版本集群使用容器镜像仓库Harbor

虚拟机 rocky9.4 linux master node01 node02 已部署k8s集群版本 1.31 方法 一 使用容器部署harbor (1) wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo yum -y install docker-ce systemctl enable docker…

数据库MYSQL——表的设计

文章目录 前言三大范式&#xff1a;几种实体间的关系&#xff1a;一对一关系&#xff1a;一对多关系&#xff1a;多对多关系&#xff1a; 前言 之前的博客中我们讲解的是关于数据库的增删改查与约束的基本操作&#xff0c; 是在已经创建数据库&#xff0c;表之上的操作。 在实…

自然语言处理: RAG优化之Embedding模型选型重要依据:mteb/leaderboard榜

本人项目地址大全&#xff1a;Victor94-king/NLP__ManVictor: CSDN of ManVictor git地址&#xff1a;https://github.com/opendatalab/MinerU 写在前面: 笔者更新不易&#xff0c;希望走过路过点个关注和赞&#xff0c;笔芯!!! 写在前面: 笔者更新不易&#xff0c;希望走过路…

《生成式 AI》课程 作业6 大语言模型(LLM)的训练微调 Fine Tuning -- part1

资料来自李宏毅老师《生成式 AI》课程&#xff0c;如有侵权请通知下线 Introduction to Generative AI 2024 Spring 该文档主要介绍了国立台湾大学&#xff08;NTU&#xff09;2024 年春季 “生成式人工智能&#xff08;GenAI&#xff09;” 课程的作业 5&#xff08;GenAI HW…

LSA详情与特殊区域

LSA是构成LSDB的重要原材料&#xff0c;在OSPF中发挥很大作用。 报文 通用头部 LS age&#xff1a;LSA寿命&#xff0c;0-3600s Options&#xff1a;可选项 LS type&#xff1a;LSA类型&#xff0c;三要素之一 Link State ID&#xff1a;LSAID 三要素之一 Advertising Ro…

网安瞭望台第4期:nuclei最新poc分享

国内外要闻 多款 D-Link 停产路由器漏洞&#xff1a;攻击者可远程执行代码 近日&#xff0c;知名网络硬件制造商 D-Link 发布重要安全公告。由于存在严重的远程代码执行&#xff08;RCE&#xff09;漏洞&#xff0c;其敦促用户淘汰并更换多款已停产的 VPN 路由器型号。 此次…

面试经典 150 题:205,55

205. 同构字符串 【解题思路】 来自大佬Krahets 【参考代码】 class Solution { public:bool isIsomorphic(string s, string t) {map<char, char> Smap, Tmap;for(int i0; i<s.size(); i){char a s[i], b t[i];//map容器存在该字符&#xff0c;且不等于之前映射…

IEC61850读服务器目录命令——GetServerDirectory介绍

IEC61850标准中的GetServerDirectory命令是变电站自动化系统中非常重要的一个功能&#xff0c;它主要用于读取服务器的目录信息&#xff0c;特别是服务器的逻辑设备节点&#xff08;LDevice&#xff09;信息。以下是对GetServerDirectory命令的详细介绍。 目录 一、命令功能 …

【PHP】 环境以及插件的配置,自学笔记(一)

文章目录 环境的准备安装 XAMPPWindowMacOS 配置开发环境Vscode 关于 PHP 的插件推荐Vscode 配置 php 环境Apache 启动Hello php配置热更新 参考 环境的准备 下载 XAMPP , 可以从 官网下载 https://www.apachefriends.org/download.html 安装 XAMPP XAMPP 是一个跨平台的集成开…

Jenkins-Git Parameter 插件实现指定版本的发布和回滚

在上一篇文章的基础设置上进行 1. 机器准备 开发10.0.0.204gitlab10.0.0.201jenkins10.0.0.200web10.0.0.202 2. 开发主机 在开发机器上修改不同版本的前端页面&#xff0c;并打上标签 第一次修改 [rootdev wheel]#vim index.html [rootdev wheel]#git commit -am "1…

vue11.22

数据代理Object.defineproperty ler person { name:张三, sex:男, age:18 } console.log(Object.keys(person)) Object.keys是把对象的属性变成数组 let person { name: 张三, sex: 男, // age: 18 } Object.defineProperty(person, age, { value: 18 }) console.log(Obj…

1、HCIP之RSTP协议与STP相关安全配置

目录 RSTP—快速生成树协议 STP STP的缺点&#xff1a; STP的选举&#xff08;Listening状态中&#xff09;&#xff1a; RSTP P/A&#xff08;提议/同意&#xff09;机制 同步机制&#xff1a; 边缘端口的配置&#xff1a; RSTP的端口角色划分&#xff1a; ensp模拟…

新160个crackme - 102-haggar-keyme1

运行分析 用win7或win xp系统可以运行输入Serial&#xff0c;点击Check无反应 PE分析 ASM程序&#xff0c;32位&#xff0c;无壳 静态分析&动态调试 ida找到关键字符串 在sub_401E6B处按x&#xff0c;返回上一步函数 来到关键函数&#xff0c;静态分析逻辑如下&#xff1a;…

LCR-003比特位计数

一.题目&#xff1a; . - 力扣&#xff08;LeetCode&#xff09; 二.我的原始解法-一次性通过的python内置bin函数解法&#xff1a; 思路和题目描述一致&#xff0c;就是把0-n的每个数字转为二进制&#xff0c;计算这个二进制中1的个数添加到返回数组中&#xff0c;掌握基础函…

动态求连续区间和(线段树 树状数组)

向上更新&#xff0c;建树&#xff0c;求区间和&#xff0c;修改节点值 向上更新&#xff1a; 返回左右节点值的和 建树&#xff1a; 如果是叶子节点&#xff0c;赋值结构体的左区间&#xff0c;右区间&#xff0c;值 如果不是叶子节点&#xff0c;那么先求中点&#xff0c…

聊聊Flink:这次把Flink的window分类(滚动、滑动、会话、全局)、窗口函数讲透

一、窗口 窗口&#xff08;Window&#xff09;是处理无界流的关键所在。窗口将流分成有限大小的“桶”&#xff0c;我们可以在其上应用算子计算。Flink可以使用window()和windowAll()定义一个窗口&#xff0c;二者都需要传入一个窗口分配器WindowAssigner&#xff0c;WindowAs…

友思特新闻 | 友思特荣获广州科技创新创业大赛智能装备行业赛初创组优胜企业!

2024年11月19日&#xff0c;第十三届中国创新创业大赛&#xff08;广东广州赛区&#xff09;暨2024年广州科技创新创业大赛智能装备行业赛颁奖典礼隆重举行。 赛事奖项介绍&#xff1a;广州科技创新创业大赛智能装备行业赛 第十三届“中国创新创业大赛&#xff08;广东广州赛区…

2024强网拟态决赛-eBeepf

漏洞分析与利用 分析后面看情况吧&#xff0c;有时间再写吧&#xff0c;先贴个利用脚本&#xff1a; #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <…