参考:http://dubbo.apache.org/zh-cn/docs/source_code_guide/dubbo-spi.html
上篇演示了dubbo spi 的一个小demo,这篇来看看源码,能力有限,不喜勿喷。
上篇的测试用例如下:
@Test
public void testExt2() throws Exception {
ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(Ext2.class);
Ext2 impl1 = extensionLoader.getExtension("impl1");
String value = impl1.echo(new UrlHolder(), "2");
System.err.println(value);
//==========================
Ext2 impl2 = extensionLoader.getExtension("impl2");
String value2 = impl2.echo(new UrlHolder(), "2");
System.err.println(value2);
}
我们从getExtensionLoader 方法跟进。
@SuppressWarnings("unchecked")
//从缓存当中获取ExtensionLoader对象,没有就构建一个新的
public static ExtensionLoader getExtensionLoader(Class type) {
if (type == null) {
throw new IllegalArgumentException("Extension type == null");
}
if (!type.isInterface()) {
throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!");
}
if (!withExtensionAnnotation(type)) {
throw new IllegalArgumentException("Extension type (" + type +
") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!");
}
ExtensionLoader loader = (ExtensionLoader) EXTENSION_LOADERS.get(type);
//没有获取到
if (loader == null) {
/***
* putIfAbsent是ConcurrentHashMap的一个方法。
* putIfAbsent方法主要是在向ConcurrentHashMap中添加键—值对的时候,它会先判断该键值对是否已经存在。
如果不存在(新的entry),那么会向map中添加该键值对,并返回null。
如果已经存在,那么不会覆盖已有的值,直接返回已经存在的值。
*/
EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader(type));
loader = (ExtensionLoader) EXTENSION_LOADERS.get(type);
}
return loader;
}
回到testExt2方法
现在来看Ext2 impl1 = extensionLoader.getExtension("impl1");
参数为一个配置文件里面配置的key,跟进getExtension 方法。
public T getExtension(String name) {
if (StringUtils.isEmpty(name)) {
throw new IllegalArgumentException("Extension name == null");
}
//如果name传入的是true则使用默认的
if ("true".equals(name)) {
return getDefaultExtension();
}
final Holder holder = getOrCreateHolder(name);
Object instance = holder.get();
//双层判断
if (instance == null) {
synchronized (holder) {
instance = holder.get();
if (instance == null) {
//创建通过名称一个实例
instance = createExtension(name);
holder.set(instance);
}
}
}
return (T) instance;
}
跟进createExtension方法找到 getExtensionClasses方法
/**
* 获取所有的拓展类
我们在通过名称获取拓展类之前,首先需要根据配置文件解析出拓展项名称到拓展类的映射关系表(Map<名称, 拓展类>),
之后再根据拓展项名称从映射关系表中取出相应的拓展类即可。相关过程的代码分析如下:
* @return
*/
private Map> getExtensionClasses() {
// 从缓存中获取已加载的拓展类
Map> classes = cachedClasses.get();
// 双重检查
if (classes == null) {
synchronized (cachedClasses) {
classes = cachedClasses.get();
if (classes == null) {
// 加载拓展类
classes = loadExtensionClasses();
cachedClasses.set(classes);
}
}
}
return classes;
}
更进loadExtensionClasses 方法
/**
* synchronized in getExtensionClasses
* 则通过 loadExtensionClasses 加载拓展类
* */
private Map> loadExtensionClasses() {
//SPI操作
cacheDefaultExtensionName();
Map> extensionClasses = new HashMap<>();
// 加载指定文件夹下的配置文件
loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName());
loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName());
loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName());
loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
return extensionClasses;
}
再来看一下SPI的操作,跟进cacheDefaultExtensionName 方法
/**
* extract and cache default extension name if exists
*/
private void cacheDefaultExtensionName() {
// 获取 SPI 注解,这里的 type 变量是在调用 getExtensionLoader 方法时传入的
final SPI defaultAnnotation = type.getAnnotation(SPI.class);
if (defaultAnnotation == null) {
return;
}
String value = defaultAnnotation.value();
if ((value = value.trim()).length() > 0) {
// 对 SPI 注解内容进行切分
String[] names = NAME_SEPARATOR.split(value);
// 检测 SPI 注解内容是否合法,不合法则抛出异常
if (names.length > 1) {
throw new IllegalStateException("More than 1 default extension name on extension " + type.getName()
+ ": " + Arrays.toString(names));
}
// 设置默认名称,参考 getDefaultExtension 方法
if (names.length == 1) {
cachedDefaultName = names[0];
}
}
}
回到loadExtensionClasses 方法看loadDirectory 方法
private void loadDirectory(Map> extensionClasses, String dir, String type) {
// fileName = 文件夹路径 + type 全限定名
String fileName = dir + type;
try {
Enumeration urls;
ClassLoader classLoader = findClassLoader();
// 根据文件名加载所有的同名文件
if (classLoader != null) {
urls = classLoader.getResources(fileName);
} else {
urls = ClassLoader.getSystemResources(fileName);
}
if (urls != null) {
while (urls.hasMoreElements()) {
java.net.URL resourceURL = urls.nextElement();
// 加载资源
loadResource(extensionClasses, classLoader, resourceURL);
}
}
} catch (Throwable t) {
logger.error("Exception occurred when loading extension class (interface: " +
type + ", description file: " + fileName + ").", t);
}
}
看一下加载资源的方法loadResource方法
private void loadResource(Map> extensionClasses, ClassLoader classLoader, java.net.URL resourceURL) {
try {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8))) {
// 按行读取配置内容
String line;
while ((line = reader.readLine()) != null) {
// 截取 # 之前的字符串,# 之后的内容为注释,需要忽略
final int ci = line.indexOf('#');
if (ci >= 0) {
line = line.substring(0, ci);
}
line = line.trim();
if (line.length() > 0) {
try {
String name = null;
// 以等于号 = 为界,截取键与值这里也就是我们在文件里看见的 key=value
int i = line.indexOf('=');
if (i > 0) {
name = line.substring(0, i).trim();
line = line.substring(i + 1).trim();
}
if (line.length() > 0) {
// 加载类,并通过 loadClass 方法对类进行缓存
loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name);
}
} catch (Throwable t) {
IllegalStateException e = new IllegalStateException("Failed to load extension class (interface: " + type + ", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t);
exceptions.put(line, e);
}
}
}
}
} catch (Throwable t) {
logger.error("Exception occurred when loading extension class (interface: " +
type + ", class file: " + resourceURL + ") in " + resourceURL, t);
}
}
跟进加载类的方法loadClass
/**
* loadClass 方法用于主要用于操作缓存
*/
private void loadClass(Map> extensionClasses, java.net.URL resourceURL, Class clazz, String name) throws NoSuchMethodException {
if (!type.isAssignableFrom(clazz)) {
throw new IllegalStateException("Error occurred when loading extension class (interface: " +
type + ", class line: " + clazz.getName() + "), class "
+ clazz.getName() + " is not subtype of interface.");
}
// 检测目标类上是否有 Adaptive 注解
if (clazz.isAnnotationPresent(Adaptive.class)) {
// 设置 cachedAdaptiveClass缓存
cacheAdaptiveClass(clazz);
} else if (isWrapperClass(clazz)) {// 检测 clazz 是否是 Wrapper 类型
cacheWrapperClass(clazz);
} else {
// 程序进入此分支,表明 clazz 是一个普通的拓展类
clazz.getConstructor();
if (StringUtils.isEmpty(name)) {
// 如果 name 为空,则尝试从 Extension 注解中获取 name,或使用小写的类名作为 name
name = findAnnotationName(clazz);
if (name.length() == 0) {
throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + resourceURL);
}
}
// 切分 name
String[] names = NAME_SEPARATOR.split(name);
if (ArrayUtils.isNotEmpty(names)) {
// 如果类上有 Activate 注解,则使用 names 数组的第一个元素作为键,
// 存储 name 到 Activate 注解对象的映射关系
cacheActivateClass(clazz, names[0]);
for (String n : names) {
cacheName(clazz, n);
// 存储 Class 到名称的映射关系
saveInExtensionClass(extensionClasses, clazz, n);
}
}
}
}
在次回到
看见画红色的方法没,这个就是dubbo的IOC实现
我们现在来分析下
跟进injectExtension方法
Dubbo IOC 是通过 setter 方法注入依赖。Dubbo 首先会通过反射获取到实例的所有方法,然后再遍历方法列表,检测方法名是否具有 setter 方法特征。若有,则通过 ObjectFactory 获取依赖对象,最后通过反射调用 setter 方法将依赖设置到目标对象中。整个过程对应的代码如下:
private T injectExtension(T instance) {
if (objectFactory == null) {
return instance;
}
try {
//遍历获取实例对象的所有方法
for (Method method : instance.getClass().getMethods()) {
//判断方法是否有setter 方法特征
// 检测方法是否以 set 开头,且方法仅有一个参数,且方法访问级别为 public
if (!isSetter(method)) {
continue;
}
/**
* 看看我们是否需要这个属性的自动注入
* Check {@link DisableInject}
*/
if (method.getAnnotation(DisableInject.class) != null) {
continue;
}
Class pt = method.getParameterTypes()[0];
if (ReflectUtils.isPrimitives(pt)) {
continue;
}
try {
// 获取 setter 方法参数类型
String property = getSetterProperty(method);
// 从 ObjectFactory 中获取依赖对象
Object object = objectFactory.getExtension(pt, property);
if (object != null) {
// 通过反射调用 setter 方法设置依赖
method.invoke(instance, object);
}
} catch (Exception e) {
logger.error("Failed to inject via method " + method.getName()
+ " of interface " + type.getName() + ": " + e.getMessage(), e);
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return instance;
}
Dubbo 目前提供了两种 ExtensionFactory,分别是 SpiExtensionFactory 和 SpringExtensionFactory。前者用于创建自适应的拓展,后者是用于从 Spring 的 IOC 容器中获取所需的拓展。
Dubbo IOC 目前仅支持 setter 方式注入。
以上就是dubbo的SPI源码,注释都写在代码里面的,如有错误之处欢迎各位盆友指正,谢谢@@@~~~~
你可能感兴趣的:(dubbo源码)
Dubbo应用接入
weixin_34281477
java python
2019独角兽企业重金招聘Python工程师标准>>>一、应用配置1、pom文件引入下面的jar包com.niwodai.infdubbo-cat-extend3.0.02、如果要对全局dubbo服务加监控,增加如下filter:服务提供方:服务消费方:如果只需要对单个服务加监控,增加如下filter:服务提供方:服务消费方:3、配置disconf开关,一个应用只需要配置一次。Disconf监控开
Ubuntu系统下交叉编译zlib
linux运维
一、参考资料【开源库编译|zlib】zlib库最新版本(zlib-1.3.1)在Ubuntu(Linux)系统下的编译、交叉编译(移植)二、交叉编译zlib1.下载源码zlib的官网地址:https://zlib.net/zlib历史发布版本下载地址:https://zlib.net/fossils/zlib在GitHub的地址:https://github.com/madler/zlib/下载并
JVM——15.定位 堆外内存 OOM
你想要怎样的未来
jvm jvm实战 java java jvm jvm.gc java虚拟机
文章目录1.ByteBuffer堆外内存介绍2.ByteBuffer堆外内存申请、释放(源码分析)2.1堆外内存申请2.2堆外内存释放3.什么情况会发生堆外内存OOM4.模拟堆外内存OOM4.1模拟14.2模拟24.3模拟35.堆外内存OOM的定位及解决1.ByteBuffer堆外内存介绍在介绍OOM那篇文章中,对堆外内存进行了介绍,就直接把它复制过来;ByteBuffer和DirectByteB
ClickHouse Keeper 源码解析
阿里云云栖号
云栖号技术分享 java 开发语言 后端
简介:ClickHouse社区在21.8版本中引入了ClickHouseKeeper。ClickHouseKeeper是完全兼容Zookeeper协议的分布式协调服务。本文对开源版本ClickHousev21.8.10.19-lts源码进行了解析。作者简介:范振(花名辰繁),阿里云开源大数据-OLAP方向负责人。内容框架背景架构图核心流程图梳理内部代码流程梳理Nuraft关键配置排坑结论关于我们R
基于大数据架构的就业岗位推荐系统的设计与实现【java或python】—计算机毕业设计源码+LW文档
qq_375279829
大数据 架构 python 课程设计 算法
摘要随着互联网技术的迅猛发展和大数据时代的到来,就业市场日益复杂多变,求职者与招聘方之间的信息不对称问题愈发突出。为解决这一难题,本文设计并实现了一个基于大数据架构的就业岗位推荐系统。该系统通过收集、整合并分析大量求职者简历信息、企业招聘信息以及市场动态数据,运用先进的机器学习算法,为求职者提供个性化的岗位推荐服务,同时帮助企业快速定位到合适的候选人。本文将从系统设计的背景与意义、技术基础、需求分
Clickhouse负载均衡客户端BalancedClickhouseDataSource源码分析
颍天
clickhouse clickhouse
文章目录BalancedClickhouseDataSource源码分析结论BalancedClickhouseDataSource源码分析BalancedClickhouseDataSource的完整路径是ru.yandex.clickhouse.BalancedClickhouseDataSource,源码主要包括三部分,构造方法、获取连接、以及生成可用的地址列表。BalancedClickh
FastExcel/EasyExcel简介以及源码解析
舌尖上的五香
java
简介官网地址GitHub地址基于MIT协议发展历史由EasyExcel发展而来2018/02/07:发布1.0.02019/09/17:发布2.0.02021/10/21:发布3.0.12024/06/18:发布4.0.02024/11/06:进入维护模式2024/12/05:发布FastExcel1.0.0主要特性高性能读写简单易用流式操作读取执行行数技术原理内存优化:基于流式读取技术,不需要一
Android Retrofit 框架注解定义与解析模块深度剖析(一)
&有梦想的咸鱼&
Android Retrofit原理 android retrofit
一、引言在现代Android和Java开发中,网络请求是不可或缺的一部分。Retrofit作为Square公司开源的一款强大的类型安全的HTTP客户端,凭借其简洁易用的API和高效的性能,在开发者社区中广受欢迎。Retrofit的核心特性之一便是通过注解来定义HTTP请求,这种方式使得代码更加清晰、易读且易于维护。本文将深入Retrofit框架的源码,对其注解定义与解析模块进行全面且细致的分析,揭
DeepSeek源码解析(1)
白鹭凡
deepseek ai
下载github的DeepSeek-V3-main源码,目录如下文章适合入门小白学习,因为我也是小白,本来作为一名前端开发,因为行业不好混所以跑来学ai的。初步看它的代码并不多,主要是inference目录,convert.py#1.导入标准库importos#os是Python的标准库之一,提供了与操作系统交互的功能,比如文件路径操作、环境变量管理等。importshutil#shutil也是P
DeepSeek源码解析(2)
白鹭凡
deepseek ai
Tensor(张量)的介绍在计算机科学和机器学习领域,“张量”(Tensor)是一个数学概念,它被用来表示多维数组。在大模型(如深度学习模型)中,张量扮演着核心角色,具体来说:数据表示:张量用于表示输入数据、模型参数和中间计算结果。例如,在图像处理中,一张图片可以被表示为一个三维张量(高度、宽度、颜色通道数),而在自然语言处理中,一段文本可以被编码为一系列词向量组成的二维张量(句子长度、词向量维度
Dubbo+zookeeper
可乐丿不加冰
zookeeper 分布式 java
Dubbo+zookeeperdubbo中文官方文档:https://dubbo.gitbooks.io/dubbo-user-book/content/preface/background.html随着互联网的高速发展,网站不断地扩大,我们的垂直应用架构无法应对,分布式服务架构以及流动计算架构势在必得,急需一个治理系统确保架构有条不紊的演进网站架构迭代:单一应用架构(所有功能都写在一个方法中)-
游戏代练新境界:uni-app赋能,一键解锁你的王者之路
phpandroid小程序
游戏代练新境界:uni-app赋能,一键解锁你的王者之路随着移动互联网的快速发展,越来越多的玩家希望通过代练系统在游戏中快速提升实力。uni-app作为一款跨平台开发框架,能够帮助开发者快速构建多端应用(如H5、小程序、App等),为游戏代练系统提供了全新的解决方案。本文将介绍如何用uni-app构建一个跨平台的代练系统,助你一键解锁王者之路!点击此处可获得完整源码和完整演示1.系统功能概述多端支
千里马Framework手机车机互联投屏实Hal+perfetto+SurfaceFlinger合集
2501_91082100
eclipse github
千里马Android手机大厂入职培训Framework系统高级开发课资料地址https://pan.baidu.com/s/1GIsMJ9BGgjgbJCrsVNDi6A?pwd=2q49千里马Android高级架构师系统源码Framework实战系列千里马Android手机大厂Framework系统-跨进程通信高级实战课千里马Android手机大厂Framework系统-Input系统专题实战课
Kotlin:Flow 全面详细指南,附带源码解析。
2401_84520377
程序员 kotlin 开发语言 android
Flow需要在协程里面使用,因为collect是挂起函数,另外基于冷流的特性,不调用collect构建器的代码压根不会走。所以只能是协程。那我取消协程不就行了吗?。好像之前有看到过有开发者提出过,是否要给flow单独加一个取消的函数,被Jetbrains无情的拒绝了,哈哈哈哈很搞笑。下面引用Kotlin官方的一段话。Flowadherestothegeneralcooperativecancell
Spring Boot 自动装配原理详解
sevevty-seven
spring boot 后端 java
SpringBoot自动装配原理详解SpringBoot的自动装配(Auto-Configuration)是其核心特性之一,它极大地简化了开发者在搭建应用时的配置工作。通过引入特定的依赖(如spring-boot-starter-web),SpringBoot能够自动配置嵌入式服务器、数据库连接等功能,而无需手动编写繁琐的配置代码。本文将深入剖析SpringBoot自动装配的原理,结合源码和详细注
点云数据处理--splat转3dtiles
gaohualan
3d python 数据结构 算法
文章目录处理流程简介核心功能实现数据读取与格式转换定义Point类数据读取splat转gltf点云数据分割定义四叉树递归生成3dtiles瓦片生成tileset.json递归生成tileset.json计算box主函数调用渲染下一步工作性能优化渲染效果调优其他源码地址:github处理流程简介基本流程:读取点云数据。制作tile构建四叉树分割点云将点云转换为glTF格式。生成配置文件tileset
Typecho插件URLAuth实现CDN URL鉴权防盗刷
是刃小木啦~
个人博客的网站搭建 人工智能 Tyepcho 网站开发
主要功能:URL鉴权机制:基于时间戳和密钥生成动态鉴权参数,确保链接在设定时间内有效,过期后自动失效。多平台兼容:支持多吉云、腾讯云、阿里云等CDN服务,配置灵活。防盗刷效果:未授权或参数错误的访问将返回403错误,且不计入CDN请求量。配置简单:通过插件后台设置密钥、鉴权范围及过期时间,无需修改源码。注意事项:不建议修改插件源码,可能导致严重问题。需了解URL鉴权的基本原理,避免误配置导致网站访
Nginx下载安装使用详解
clownAdam
nginx nginx 运维
Nginx下载安装使用详解Nginx是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP代理服务器。它以其高并发处理能力、低内存消耗和模块化架构而闻名。以下是Nginx的下载、安装和基本使用的详细步骤。1.下载Nginx你可以从Nginx的官方网站下载最新版本的源码包,或者通过包管理器安装。1.1从官网下载源码包访问Nginx官方网站,选择适合的版本进行下载。例如:wget
Python3的安装
Ladeng_uncle
python python 后端
环境信息操作系统:CentOSLinuxrelease7.6.1810Python:3.6.5现状说明当前CentOS系统自带了python2.7.5,因为yum会用到python2,所以不能删除,此次安装了python3之后就保持两个版本长期共存吧。本次安装采用的是下载python源码再编译的方式;操作步骤以root身份登录CentOS,以下操作都在默认的~目录下:1、yum更新:yumupda
2024年HarmonyOS鸿蒙最全HarmonyOS Next 自定义路由栈管理_navpathstack,2024年最新销售应届毕业生的面试题
2401_84870988
程序员 鸿蒙 面试 学习
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新需要这份系统化的资料的朋
计算机毕业设计springboot晋中学院失物招领系统的设计与实现unst3源码+系统+程序+lw文档+部署
呦呦网络
spring boot java mysql
计算机毕业设计springboot晋中学院失物招领系统的设计与实现unst3源码+系统+程序+lw文档+部署计算机毕业设计springboot晋中学院失物招领系统的设计与实现unst3源码+系统+程序+lw文档+部署本源码技术栈:项目架构:B/S架构开发语言:Java语言开发软件:ideaeclipse前端技术:Layui、HTML、CSS、JS、JQuery等技术后端技术:JAVA运行环境:Wi
计算机毕业设计JAVA人职匹配推荐系统mybatis+源码+调试部署+系统+数据库+lw
诺诺网络
java mybatis 开发语言
计算机毕业设计JAVA人职匹配推荐系统mybatis+源码+调试部署+系统+数据库+lw计算机毕业设计JAVA人职匹配推荐系统mybatis+源码+调试部署+系统+数据库+lw本源码技术栈:项目架构:B/S架构开发语言:Java语言开发软件:ideaeclipse前端技术:Layui、HTML、CSS、JS、JQuery等技术后端技术:JAVA运行环境:Win10、JDK1.8数据库:MySQL5
EDPose:探讨端到端的实时多人姿态估计
烧技湾
AI & Computer Vision HPE 人体姿态估计 端到端检测
作者:曾爱玲(港中文博士,现已入职腾讯)单位:IDEA(深圳数字经济研究院)源码:github/ED-Pose该篇论文取得效果如下:这篇文章的优势在于:在复杂的多人场景下能够取得不错的性能提升,虽然在COCO等数据集上的提升不明显。这种端到端的方法,优势在于检测到人体是检测到关键点的一个保证。目录摘要一、介绍二、相关工作2.1.单阶段多人姿态估计2.2检测变压器:三、重新思考单阶段多人姿态估计3.
【python爬虫】免费爬取网易云音乐完整教程(附带源码)
景天科技苑
爬虫副业实战 零基础 进阶教学 python 爬虫 开发语言 js逆向
✨✨欢迎大家来到景天科技苑✨✨养成好习惯,先赞后看哦~所属专栏:爬虫实战,零基础、进阶教学景天的主页:景天科技苑文章目录网易云逆向网易云逆向https://music.163.com/下载云音乐胡广生等,可以选择自己喜欢的歌曲首先,我们可以先根据抓包找到的m4a文件,下载试试在这个请求
PyBroker: 使用Python进行机器学习驱动的算法交易指南
任铃冰Flourishing
PyBroker:使用Python进行机器学习驱动的算法交易指南pybrokerAlgorithmicTradinginPythonwithMachineLearning项目地址:https://gitcode.com/gh_mirrors/py/pybroker一、项目目录结构及介绍PyBroker项目遵循了清晰的组织结构来简化其源码管理和维护。以下是该仓库的主要目录及其简介:├──docs#文
技术人实测 | 如何用AI工具2分钟突破知网AIGC检测线
LL06210721
人工智能 AIGC
最近在GitHub发现个有意思的本地化算法工具,其核心是通过对抗式语义重组技术重构文本逻辑链。测试时发现:将GPT生成的论文导入后,系统会保留原始参考文献格式,同时用学术同义词替换引擎重写表达结构。实测数据:某985实验室的AI生成稿经处理,知网AIGC率从38%→9.7%(检测截图已脱敏),维普重复率从24%→8.3%。工具最实用的三个细节:保留公式编号和图表位置不变支持LaTeX源码级修改追踪
Android源码编译命令详解
龙之叶
Android framework 系统定制 android java linux 开源 ubuntu
一、引言先看下面几条指令,相信编译过Android源码的人都再熟悉不过的。sourcesetenv.shlunchmake-j8记得最初刚接触Android时,同事告诉我用上面的指令就可以编译Android源码,指令虽短但过几天就记不全或者忘记顺序,每次编译时还需要看看自己的云笔记,冰冷的指令总是难以让我记忆。后来我决定认真研究下这个指令的含义。知其然还需知其所以然,这样能更深层次的理解并记忆,才
解析:婚恋交友系统APP源码开发攻略,语音视频聊天功能实现步骤核心功能
前端后端小程序数据库程序员
系统功能特点1.自定义小程序管理:本系统提供完整的后台管理功能,开发者可以根据自己的需求进行定制和修改,包括但不限于论坛版块管理、帖子管理、用户管理等功能。后台管理界面简洁明了,操作方便,大大降低了开发门槛。2.完整的安装代码包:本系统提供完整的安装代码包,包括小程序前端代码、后端服务代码以及数据库结构等。开发者只需按照说明进行安装和配置,即可快速搭建起一个功能完备的社区论坛小程序。3.丰富的功能
SpringBoot统一功能处理——统一异常处理
棕豆兔&
spring boot spring java
目录一、异常简单使用二、@ControllerAdvice源码分析一、异常简单使用统一异常处理使用的是@ControllerAdvice+@ExceptionHandler来实现的,@ControllerAdvice表示控制器通知类,@ExceptionHandler是异常处理器,两个结合表示当出现异常的时候执行某个通知,也就是执行某个方法事件。importcom.example.demo.mod
RocketMQ的Consumer源码分析
foolishboy_w
后台技术 rocketmq java-rocketmq rocketmq java
RocketMQ的Consumer源码分析文章目录RocketMQ的Consumer源码分析Consumer的Rebalance流程Consumer的消息拉取流程Consumer的Offset管理这一节我们分析RocketMQ的Consumer的启动流程以及消息处理过程。下图是RocketMQ启动流程、Rebalance、以及消息拉取处理的较为完整的流程图。##Consumer的启动流程Consu
312个免费高速HTTP代理IP(能隐藏自己真实IP地址)
yangshangchuan
高速 免费 superword HTTP代理
124.88.67.20:843
190.36.223.93:8080
117.147.221.38:8123
122.228.92.103:3128
183.247.211.159:8123
124.88.67.35:81
112.18.51.167:8123
218.28.96.39:3128
49.94.160.198:3128
183.20
pull解析和json编码
百合不是茶
android pull解析 json
n.json文件:
[{name:java,lan:c++,age:17},{name:android,lan:java,age:8}]
pull.xml文件
<?xml version="1.0" encoding="utf-8"?>
<stu>
<name>java
[能源与矿产]石油与地球生态系统
comsci
能源
按照苏联的科学界的说法,石油并非是远古的生物残骸的演变产物,而是一种可以由某些特殊地质结构和物理条件生产出来的东西,也就是说,石油是可以自增长的....
那么我们做一个猜想: 石油好像是地球的体液,我们地球具有自动产生石油的某种机制,只要我们不过量开采石油,并保护好
类与对象浅谈
沐刃青蛟
java 基础
类,字面理解,便是同一种事物的总称,比如人类,是对世界上所有人的一个总称。而对象,便是类的具体化,实例化,是一个具体事物,比如张飞这个人,就是人类的一个对象。但要注意的是:张飞这个人是对象,而不是张飞,张飞只是他这个人的名字,是他的属性而已。而一个类中包含了属性和方法这两兄弟,他们分别用来描述对象的行为和性质(感觉应该是
新站开始被收录后,我们应该做什么?
IT独行者
PHP seo
新站开始被收录后,我们应该做什么?
百度终于开始收录自己的网站了,作为站长,你是不是觉得那一刻很有成就感呢,同时,你是不是又很茫然,不知道下一步该做什么了?至少我当初就是这样,在这里和大家一份分享一下新站收录后,我们要做哪些工作。
至于如何让百度快速收录自己的网站,可以参考我之前的帖子《新站让百
oracle 连接碰到的问题
文强chu
oracle
Unable to find a java Virtual Machine--安装64位版Oracle11gR2后无法启动SQLDeveloper的解决方案
作者:草根IT网 来源:未知 人气:813标签:
导读:安装64位版Oracle11gR2后发现启动SQLDeveloper时弹出配置java.exe的路径,找到Oracle自带java.exe后产生的路径“C:\app\用户名\prod
Swing中按ctrl键同时移动鼠标拖动组件(类中多借口共享同一数据)
小桔子
java 继承 swing 接口 监听
都知道java中类只能单继承,但可以实现多个接口,但我发现实现多个接口之后,多个接口却不能共享同一个数据,应用开发中想实现:当用户按着ctrl键时,可以用鼠标点击拖动组件,比如说文本框。
编写一个监听实现KeyListener,NouseListener,MouseMotionListener三个接口,重写方法。定义一个全局变量boolea
linux常用的命令
aichenglong
linux 常用命令
1 startx切换到图形化界面
2 man命令:查看帮助信息
man 需要查看的命令,man命令提供了大量的帮助信息,一般可以分成4个部分
name:对命令的简单说明
synopsis:命令的使用格式说明
description:命令的详细说明信息
options:命令的各项说明
3 date:显示时间
语法:date [OPTION]... [+FORMAT]
eclipse内存优化
AILIKES
java eclipse jvm jdk
一 基本说明 在JVM中,总体上分2块内存区,默认空余堆内存小于 40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。 1)堆内存(Heap memory):堆是运行时数据区域,所有类实例和数组的内存均从此处分配,是Java代码可及的内存,是留给开发人
关键字的使用探讨
百合不是茶
关键字
//关键字的使用探讨/*访问关键词private 只能在本类中访问public 只能在本工程中访问protected 只能在包中和子类中访问默认的 只能在包中访问*//*final 类 方法 变量 final 类 不能被继承 final 方法 不能被子类覆盖,但可以继承 final 变量 只能有一次赋值,赋值后不能改变 final 不能用来修饰构造方法*///this()
JS中定义对象的几种方式
bijian1013
js
1. 基于已有对象扩充其对象和方法(只适合于临时的生成一个对象):
<html>
<head>
<title>基于已有对象扩充其对象和方法(只适合于临时的生成一个对象)</title>
</head>
<script>
var obj = new Object();
表驱动法实例
bijian1013
java 表驱动法 TDD
获得月的天数是典型的直接访问驱动表方式的实例,下面我们来展示一下:
MonthDaysTest.java
package com.study.test;
import org.junit.Assert;
import org.junit.Test;
import com.study.MonthDays;
public class MonthDaysTest {
@T
LInux启停重启常用服务器的脚本
bit1129
linux
启动,停止和重启常用服务器的Bash脚本,对于每个服务器,需要根据实际的安装路径做相应的修改
#! /bin/bash
Servers=(Apache2, Nginx, Resin, Tomcat, Couchbase, SVN, ActiveMQ, Mongo);
Ops=(Start, Stop, Restart);
currentDir=$(pwd);
echo
【HBase六】REST操作HBase
bit1129
hbase
HBase提供了REST风格的服务方便查看HBase集群的信息,以及执行增删改查操作
1. 启动和停止HBase REST 服务 1.1 启动REST服务
前台启动(默认端口号8080)
[hadoop@hadoop bin]$ ./hbase rest start
后台启动
hbase-daemon.sh start rest
启动时指定
大话zabbix 3.0设计假设
ronin47
What’s new in Zabbix 2.0?
去年开始使用Zabbix的时候,是1.8.X的版本,今年Zabbix已经跨入了2.0的时代。看了2.0的release notes,和performance相关的有下面几个:
:: Performance improvements::Trigger related da
http错误码大全
byalias
http协议 javaweb
响应码由三位十进制数字组成,它们出现在由HTTP服务器发送的响应的第一行。
响应码分五种类型,由它们的第一位数字表示:
1)1xx:信息,请求收到,继续处理
2)2xx:成功,行为被成功地接受、理解和采纳
3)3xx:重定向,为了完成请求,必须进一步执行的动作
4)4xx:客户端错误,请求包含语法错误或者请求无法实现
5)5xx:服务器错误,服务器不能实现一种明显无效的请求
J2EE设计模式-Intercepting Filter
bylijinnan
java 设计模式 数据结构
Intercepting Filter类似于职责链模式
有两种实现
其中一种是Filter之间没有联系,全部Filter都存放在FilterChain中,由FilterChain来有序或无序地把把所有Filter调用一遍。没有用到链表这种数据结构。示例如下:
package com.ljn.filter.custom;
import java.util.ArrayList;
修改jboss端口
chicony
jboss
修改jboss端口
%JBOSS_HOME%\server\{服务实例名}\conf\bindingservice.beans\META-INF\bindings-jboss-beans.xml
中找到
<!-- The ports-default bindings are obtained by taking the base bindin
c++ 用类模版实现数组类
CrazyMizzz
C++
最近c++学到数组类,写了代码将他实现,基本具有vector类的功能
#include<iostream>
#include<string>
#include<cassert>
using namespace std;
template<class T>
class Array
{
public:
//构造函数
hadoop dfs.datanode.du.reserved 预留空间配置方法
daizj
hadoop 预留空间
对于datanode配置预留空间的方法 为:在hdfs-site.xml添加如下配置
<property>
<name>dfs.datanode.du.reserved</name>
<value>10737418240</value>
mysql远程访问的设置
dcj3sjt126com
mysql 防火墙
第一步: 激活网络设置 你需要编辑mysql配置文件my.cnf. 通常状况,my.cnf放置于在以下目录: /etc/mysql/my.cnf (Debian linux) /etc/my.cnf (Red Hat Linux/Fedora Linux) /var/db/mysql/my.cnf (FreeBSD) 然后用vi编辑my.cnf,修改内容从以下行: [mysqld] 你所需要: 1
ios 使用特定的popToViewController返回到相应的Controller
dcj3sjt126com
controller
1、取navigationCtroller中的Controllers
NSArray * ctrlArray = self.navigationController.viewControllers;
2、取出后,执行,
[self.navigationController popToViewController:[ctrlArray objectAtIndex:0] animated:YES
Linux正则表达式和通配符的区别
eksliang
正则表达式 通配符和正则表达式的区别 通配符
转载请出自出处:http://eksliang.iteye.com/blog/1976579
首先得明白二者是截然不同的
通配符只能用在shell命令中,用来处理字符串的的匹配。
判断一个命令是否为bash shell(linux 默认的shell)的内置命令
type -t commad
返回结果含义
file 表示为外部命令
alias 表示该
Ubuntu Mysql Install and CONF
gengzg
Install
http://www.navicat.com.cn/download/navicat-for-mysql
Step1: 下载Navicat ,网址:http://www.navicat.com/en/download/download.html
Step2:进入下载目录,解压压缩包:tar -zxvf navicat11_mysql_en.tar.gz
批处理,删除文件bat
huqiji
windows dos
@echo off
::演示:删除指定路径下指定天数之前(以文件名中包含的日期字符串为准)的文件。
::如果演示结果无误,把del前面的echo去掉,即可实现真正删除。
::本例假设文件名中包含的日期字符串(比如:bak-2009-12-25.log)
rem 指定待删除文件的存放路径
set SrcDir=C:/Test/BatHome
rem 指定天数
set DaysAgo=1
跨浏览器兼容的HTML5视频音频播放器
天梯梦
html5
HTML5的video和audio标签是用来在网页中加入视频和音频的标签,在支持html5的浏览器中不需要预先加载Adobe Flash浏览器插件就能轻松快速的播放视频和音频文件。而html5media.js可以在不支持html5的浏览器上使video和audio标签生效。 How to enable <video> and <audio> tags in
Bundle自定义数据传递
hm4123660
android Serializable 自定义数据传递 Bundle Parcelable
我们都知道Bundle可能过put****()方法添加各种基本类型的数据,Intent也可以通过putExtras(Bundle)将数据添加进去,然后通过startActivity()跳到下一下Activity的时候就把数据也传到下一个Activity了。如传递一个字符串到下一个Activity
把数据放到Intent
C#:异步编程和线程的使用(.NET 4.5 )
powertoolsteam
.net 线程 C# 异步编程
异步编程和线程处理是并发或并行编程非常重要的功能特征。为了实现异步编程,可使用线程也可以不用。将异步与线程同时讲,将有助于我们更好的理解它们的特征。
本文中涉及关键知识点
1. 异步编程
2. 线程的使用
3. 基于任务的异步模式
4. 并行编程
5. 总结
异步编程
什么是异步操作?异步操作是指某些操作能够独立运行,不依赖主流程或主其他处理流程。通常情况下,C#程序
spark 查看 job history 日志
Stark_Summer
日志 spark history job
SPARK_HOME/conf 下:
spark-defaults.conf 增加如下内容
spark.eventLog.enabled true spark.eventLog.dir hdfs://master:8020/var/log/spark spark.eventLog.compress true
spark-env.sh 增加如下内容
export SP
SSH框架搭建
wangxiukai2015eye
spring Hibernate struts
MyEclipse搭建SSH框架 Struts Spring Hibernate
1、new一个web project。
2、右键项目,为项目添加Struts支持。
选择Struts2 Core Libraries -<MyEclipes-Library>
点击Finish。src目录下多了struts