皮皮网

【水果网站java源码】【mysql 5.6源码】【moba类源码】plugin插件源码_插件源代码

2024-12-26 00:36:22 来源:nginxreload源码分析

1.源码细读-深入了解terser-webpack-plugin的插件插件实现
2.[Mybatis]-[基础支持层]-插件-plugin标签解析
3.maven-compiler-plugin编译插件
4.一文搞懂Mybatis插件原理
5.plugin历史渊源
6.详解webpackplugin的原理及编写一个plugin

plugin插件源码_插件源代码

源码细读-深入了解terser-webpack-plugin的实现

       terser-webpack-plugin 是一个基于 webpack 的插件,它利用 terser 库对 JavaScript 代码进行压缩和混淆。源码源代其核心功能在于通过在 webpack 的插件插件运行时钩子 optimizeChunkAssets 中注册,实现了代码优化过程。源码源代在 apply 函数中,插件插件它获取 compilation 实例,源码源代水果网站java源码并通过 tapPromise 注册一个异步任务,插件插件当 webpack 执行优化阶段时,源码源代每个 chunk 会触发这个任务,插件插件执行 minify 函数进行压缩处理。源码源代

       optimise 函数是插件插件实际的任务处理入口,它负责具体的源码源代优化流程。函数内部,插件插件scheduleTask 负责并行处理,源码源代如果开启 parallel 模式,插件插件会利用jest-worker提供的线程池进行并发工作,线程池管理复杂,根据 node 版本不同采用 worker_threads 或 child_process。minify 函数则是压缩和混淆代码的核心操作,它直接使用 terser 库完成任务。mysql 5.6源码

       总的来说,terser-webpack-plugin 的优化流程包括在 webpack 的优化阶段对代码进行压缩,使用 Jest 的 worker 线程池进行并行处理,以及通过 terser 库的实际压缩操作。理解这些核心环节,可以帮助开发者更深入地掌握该插件的使用和工作原理。

[Mybatis]-[基础支持层]-插件-plugin标签解析

       该系列文章针对 Mybatis 3.5.1 版本

       一、Mybatis 插件的作用

       Mybatis 针对SQL映射语句执行过程进行拦截处理,而对应的拦截器 Mybaits 又称之为插件(这些插件就是Mybatis的扩展点)。

       在 Mybaits 中允许用插件来拦截的方法包括:

       通过插件的方式可以实现SQL打印、分页等插件功能实现。

       二、Mybatis 插件配置

       插件代码逻辑实现后还需要加载到 Mybatis 中才能生效,Mybatis 提供了配置标签,用来声明。

       插件在mybatis-config.xml 中的配置案例,如下:

       通过 标签,然后在指定的属性 interceptor 配置插件实现类的全路径即可。

       三、moba类源码`plugin` 标签解析

       再来回顾一下,XMLConfigBuilder解析时序简图,如下:

       在时序图中加载解析在XMLConfigBuilder#pluginElement中完成,相关解析代码如下:

       如上述代码,`plugin` 的解析流程很简单

       1、加载 `plugin` 下的子标签

       2、获取 `plugin` 中 interceptor 属性中的 class 全路径名

       3、class 必须实现了 Interceptor接口,如果满足,通过反射实例化类

       4、把类加载到存放拦截器的拦截器容器,拦截器链 InterceptorChain

       简单来看一下InterceptorChain 代码定义

       如上述代码所示,InterceptorChain 本身就是一个容器,用来存放所有从 `plugin` 读取到的拦截器对象。

       而这里的拦截器列表,在使用过程中,会通过代理的方式,对目标对象层层代理,通过责任链的情趣商城源码方式实现代码执行前后的层层过滤,相关逻辑图如下:

       四、interceptor 过滤链代理处理代码

       上面提到了 interceptor 过滤链的实现是通过代理的方式层层包裹实现的,下面来简单阅读代理流程源码

       Mybatis 中只针对 Executor、ParameterHandler、ResultSetHandler、StatementHandler,这四种情况追加了过滤连的处理。

       相关的处理方法入口为InterceptorChain#pluginAll,如下图

       如上述代码,遍历所有的插件,调用插件本身的 plugin 方法来处理,也就是 Interceptor#plugin,来看通用实现

       (也可以自定义实现逻辑),代码如下

       如上述代码,通用的代理逻辑交由工具类 Plugin 来实现,

       接着来看一下 Plugin#wrap 方法源码

       如上述源码所示,通过配对当前 interceptor 是否符合目标对象 target ,如果配对,构建相应的-123的源码代理对象。

       以此类推,随后实现如下图的效果:

       五、总结

       通过上述源码解析能够知道一个插件,也就是一个 Interceptor 的定义需要满足两个条件

       1、该插件实现类实现了 Interceptor 接口

       2、该插件实现类通过注解 @Intercepts 指定了该插件需要拦截的对象,也就是 Executor、ParameterHandler、ResultSetHandler、StatementHandler 中的一种或者多种

       `plugin` 标签中配置的是一系列拦截器,这些拦截器通过代理的方式组合起来实现了过滤器链。

       而这些过滤器数据存储在 InterceptorChain 中,最终数据仍然会存在 Configuration 中,相关的 Configuration 逻辑图如下:

maven-compiler-plugin编译插件

       在Java项目开发中,Maven的maven-compiler-plugin编译插件扮演了至关重要的角色,它简化了编译过程,允许自定义编译步骤。以下是关于该插件的详细说明:

       默认情况下,maven-compiler-plugin负责了Java项目的编译任务,相当于命令行中的javac。为了进行个性化配置,开发者可以在pom.xml中添加如下内容:

       设定版本号,可自定义,maven会自动选择合适的版本。

       配置编译器,如设置源代码编码、输出详细信息、指定编译器路径(executable),默认是利用JAVA_HOME,也可指定绝对路径。

       管理内存使用,包括最小和最大内存,确保编译效率。

       明确源代码和目标代码的语言级别,支持精确指定版本差异。

       还可以通过release属性替代指定编译属性。

       若想使用外部编译器(如Plexus Compiler),需在pom.xml中设置compilerId和fork标签。

       对于JDK9+的兼容性,可能需要进行两次编译,配置方法有所变化,具体取决于兼容的JDK版本。

       总的来说,虽然maven-compiler-plugin默认配置已能满足大部分项目,但对于特定需求,灵活的配置选项提供了强大的支持。

一文搞懂Mybatis插件原理

       Mybatis插件原理详解,让你轻松实现自定义功能

       在深入Mybatis源码时,你可能会遇到名为"plugin"的包,这实际上用于扩展框架的功能,如PageHelper分页插件。本文将揭示插件的运作机制,教你如何理解其内部工作并自行实现,如分页或慢SQL统计。

       使用PageHelper插件分页的简单步骤是:一,在pom.xml中添加依赖;二,在mybatis-config.xml中配置插件;三,在需要分页的mapper接口前调用startPage方法,并确保每次查询后关闭Page对象以避免数据冲突。

       接下来,我们将探索插件的总体流程:首先,通过拦截器接口实现动态代理,如PageInterceptor,它会在Executor的query方法执行前后添加自定义逻辑。拦截器通过Invocation对象获取目标对象和方法参数,实现增强功能。

       分页拦截器如PageInterceptor拦截query方法,若需要分页,会获取原始SQL并添加limit语句。配置插件时,在mybatis-config.xml中添加相应拦截器,如``标签和Interceptor实现类的全限定名。

       当我们创建SqlSession时,拦截器通过Configuration的newExecutor方法注册并应用到Executor对象上,利用JDK动态代理生成增强的代理对象,从而在执行SQL时调用拦截器的intercept方法。

       自定义慢SQL统计插件同样基于Interceptor,只需配置目标对象为StatementHandler,拦截方法为query、update或batch,然后在配置文件中添加插件的全限定名。

plugin历史渊源

       插件的概念追溯至上世纪七十年代。当时在Univac /系列主机的Unisys VS/9操作系统中,运行着一个名为EDT的文本编辑器。此编辑器具有独特功能,能从编辑器中运行其他应用程序,并允许这些程序访问编辑器的缓冲区,让程序在内存中进行文本操作。这一功能随后被Waterloo Fortran编译器采用,与EDT编辑的Fortran程序进行交互编译。

       插件功能在个人电脑上的首次应用可能出现在年的Macintosh上,HyperCard和QuarkXPress软件中均包含了此功能。年,Silicon Beach软件公司将其引入到Digital Darkroom和SuperPaint软件中,使得这些软件更加灵活与强大。然而,"插件"这一术语是由Ed Bomke提出并广泛使用的。

       简言之,插件概念的起源可追溯至上世纪七十年代的主机操作系统,它允许应用程序访问共享缓冲区进行文本操作。随着个人电脑的普及,插件功能逐渐扩展至多种软件应用中,丰富了软件的功能性与灵活性。"插件"一词的正式命名则是在九十年代初由Ed Bomke提出,标志着插件这一概念在软件开发领域的广泛应用。

扩展资料

       Plugin(Plug-in,addin,add-in,addon或add-on)是一种计算机应用程序,它和主应用程序(host application)互相交互,以提供特定的功能。应用程序支持Plugin有许多原因,一些主要原因包括:使得第三方开发者有能力扩展应用程序,以提供无法先期预料的特色;减小应用程序的大小;由于软件版权之间的不兼容性将源代码和应用程序分享。

详解webpackplugin的原理及编写一个plugin

       plugin解决了什么问题?

       plugin解决了Webpack构建生命周期过程中的功能定制问题,可以利用plugin参与到webpack构建流程中的各个阶段并劫持做一些代码处理。

       æ¯”如,打包后需要生成一个html文件,那么就可以使用html-webpack-plugin。还有,在打包之前把dist文件删除,就可以使用clean-webpack-plugin。

       webpack本身就是一个构建过程的状态机,其自身的核心功能也是构建在loader和plugin的机制上的。

compiler和compilation具体是干什么的?

       é¦–先我们来看一个webpack自带的插件BannerPlugin代码,其实webpack的很多核心公司就是利用插件来实现的。

       æ’件的格式

       ä¸€ä¸ªJavaScript函数或JavaScriptç±»;

       åœ¨å®ƒåŽŸåž‹ä¸Šå®šä¹‰çš„apply方法,会在安装插件时被调用,并被webpackcompiler调用一次;

       æŒ‡å®šä¸€ä¸ªè§¦åŠåˆ°webpack本身的事件钩子,即hooks,用于特定时机处理额外的逻辑;

classBannerPlugin{ constructor(options){ this.options=options;}apply(compiler){ constoptions=this.options;constbanner=this.banner;compiler.hooks.compilation.tap("BannerPlugin",compilation=>{ compilation.hooks.processAssets.tap({ name:"BannerPlugin"},()=>{ for(constchunkofcompilation.chunks){ for(constfileofchunk.files){ constdata={ chunk,filename:file};//生成注释constcomment=compilation.getPath(banner,data);//把注释加入到文件中compilation.updateAsset(file,old=>{ constsource=options.footer?newConcatSource(old,"\n",comment):newConcatSource(comment,"\n",old);returnsource;}});}}}}}}

       ä»Žä»£ç ä¸­å‡ºçŽ°äº†compiler和compilation,那它们到底是什么呢?

compiler

       compiler模块是Webpack最核心的模块。每次执行Webpack构建的时候,在Webpack内部,会首先实例化一个Compiler对象,然后调用它的run方法来开始一次完整的编译过程。compiler对象代表了完整的webpack环境配置,插件可以通过它获取到webpack的配置信息,如entry、output、module等配置。

       compiler钩子compiler有很多钩子,下面只介绍常用的几个:钩子名?|Tapable类型|触发时机|传入callback的参数?||--------------------|-----------------|------------------------------------------|---------------------------------||entryOption?|SyncBailHook|在webpack中的entry配置处理过之后|context,entry||afterPlugins|SyncHook?|初始化完内置插件之后|compiler||environment?|SyncHook?|准备编译环境,webpackplugins配置初始化完成之后?|compiler||beforeRun?|AsyncSeriesHook?|开始正式编译之前?|compiler||run|AsyncSeriesHook?|开始编译之后,读取records之前;|compiler||compile|SyncHook?|一次compilation编译创建之前|compilationParams||compilation?|SyncHook?|compilation创建成功之后?|compilation,compilationParams||emit|AsyncSeriesHook?|生成资源到output目录之前?|compilation?||done|AsyncSeriesHook?|compilation完成之后?|stats?||failed|SyncHook?|compilation失败|

       æ•´ä¸ªCompiler完整地展现了Webpack的构建流程:

       å‡†å¤‡é˜¶æ®µï¼šmake之前做的事情都属于准备阶段,这阶段的calback入参以compiler为主;

       ç¼–译阶段:这阶段以compilation的钩子为主,calback入参以compilation为主;

       äº§å‡ºé˜¶æ®µï¼šè¿™é˜¶æ®µä»Žcompilation开始,最后回到Compiler钩子上,calback传入参数是跟结果相关的数据,包括stats、error。

compilation

       åœ¨compilation阶段,模块会被加载(loaded)、封存(sealed)、优化(optimized)、分块(chunked)、哈希(hashed)和重新创建(restored),Compilation对象包含了当前的模块资源、编译生成资源、变化的文件等。Compilation对象也提供了很多事件回调供插件做扩展,通过Compilation也能读取到Compiler对象。

       Compilation钩子

       åœ¨Compilation中处理的对象分别是module、chunk、assets,由modules组成chunks,由chunks生成assets,处理顺序是:module→modules→chunks→assets,先从单个module开始处理,查找依赖关系,最后完成单个module处理,完成全部modules之后,开始chunks阶段处理,最后在根据优化配置,按需生成assets。

       æ‰€ä»¥æ•´ä¸ªCompilation的生命周期钩子虽然比较多,但是大规律上是围绕这个顺序进行的,具体的钩子可以查看webpack官网。

       Stats对象在Webpack的回调函数中会得到stats对象。这个对象实际来自于Compilation.getStats(),返回的是主要含有modules、chunks和assets三个属性值的对象。

       modules:记录了所有解析后的模块;

       chunks:记录了所有chunk;

       assets:记录了所有要生成的文件。

       æœ‰äº†å¯¹compilercompilation的理解,那现在来看看BannerPlugin的实现,这个插件的功能是在最后生成的文件的头部加上一段我们自定义的注释,那么它的执行时机肯定是在编译完成之后,生成打包文件之间,也就是在compiler.hooks.compilation这个大钩子下面的processAssets钩子里面执行我们的逻辑。

编写pluginplugin:在文件尾部插入一段注释

       é¦–先创建一个plugins/FootPlugin.js,代码如下:

const{ ConcatSource}=require('webpack-sources')classFootPlugin{ constructor(options){ this.options=options}apply(compiler){ compiler.hooks.compilation.tap('FootPlugin',compilation=>{ compilation.hooks.processAssets.tap('FootPlugin',()=>{ for(constchunkofcompilation.chunks){ for(constfileofchunk.files){ console.log('file--',file)//bundle.js//定义注释的内容constcomment=`/*${ this.options.banner}*/`compilation.updateAsset(file,old=>{ //把注释和旧代码进行拼接returnnewConcatSource(old,'\n',comment)})}}})})}}module.exports=FootPlugin

       webpack.config.js

constFootPlugin=require('./plugins/FootPlugin')module.exports={ plugins:[newwebpack.BannerPlugin({ banner:'欢迎学习'}),newFootPlugin({ banner:'结束学习'})]}

       å¯ä»¥çœ‹åˆ°åœ¨bundle.js的开头和结尾都有对应的注释。

plugin:文件超过一定大小时给出警告const{ resolve}=require('path')constfs=require('fs')classBundleSizeWebpackPlugin{ constructor(options){ this.options=options}apply(compiler){ const{ sizeLimit}=this.optionsconsole.log('bundlesizeplugin')//在编译完成后,执行回调,拿到打包后文件路径,然后读取文件信息获取文件大小,然后定义一些逻辑compiler.hooks.done.tap('BundleSizePlugin',stats=>{ const{ path,filename}=stats.compilation.outputOptionsconstbundlePath=resolve(path,filename)const{ size}=fs.statSync(bundlePath)constbundleSize=size/if(bundleSize<sizeLimit){ console.log('safe:bundle-size',bundleSize,'\nsizelimit:',sizeLimit)}else{ console.warn('unsafe:bundle-size',bundleSize,'\nsizelimit:',sizeLimit)}})}}module.exports=BundleSizeWebpackPlugin

       æœ¬ç« åˆ°è¿™é‡Œå°±ç»“束了,我们开始介绍了webpack的核心概念,有了对webpack的基本配置的了解;接着利用css-loader和style-loader对webpack的loader机制进行了详细分析;最后,对webpackplugin的工作机制和流程进行了梳理,并手写了两个plugin,让你对plugin不再觉得遥不可及。有了这些前置知识,就可以对我们原生项目进行工程化的改造了。期待你的学习。

原文:/post/