1.Vue—关于插件(源码级别的电脑电脑插件分析+实践)
2.手写一个简单的谷歌浏览器拓展插件(附github源码)
3.mybatis插件机制源码解析
4.电脑上最好用的速记工具
5.UEC++插件开发笔记
6.掌控自己的内容:使用 Obsidian 打造个人知识管理系统(三):必备插件安装
Vue—关于插件(源码级别的插件分析+实践)
Vue插件的原理基于Vue的`use`方法,该方法接收一个函数或者提供`install`方法的插件插件对象作为参数,如果传入的源码源码参数是函数,这个函数会被当作`install`方法。笔记笔记本用在Vue 2.6.版本中,电脑电脑`use`方法内部使用`initUse`函数给Vue添加了一个静态方法`use`。插件插件同城口令雷源码以vuex为例,源码源码它暴露了一个`install`方法,笔记笔记本用通过`Vue.use(vuex)`来安装插件。电脑电脑vuex的插件插件`install`函数会调用`applyMixin`函数,并将Vue传递过去。源码源码`applyMixin`函数在Vue 2.x版本中会直接使用`Vue.mixin`来扩展功能,笔记笔记本用通过在组件的电脑电脑`beforeCreate`钩子中初始化vuex插件。
在Vue中使用混入(mixin)是插件插件一种设计模式,可以轻松地被子类继承功能,源码源码目的是实现函数复用。Vue中也应用了这一设计模式,通过`Vue.mixin`可以用来分发可复用逻辑。混入可以分为全局混入和局部混入,全局混入会影响所有的Vue实例,如果组件中与mixin中具有同名的属性,会进行选项合并,除了生命周期外,其它的所有属性都会被组件自身的属性覆盖。使用混入可以节省代码量,类似于类继承。
要自己实现一个提示框插件,可以通过`this.$notify()`进行调用,并且可以传入自定义模板。创建一个Vue工程,ssi项目源码在`src`目录下新建`plugin`目录,然后创建一个`notify`目录,新建`index.js`和`Notify.vue`。在`index.js`中,引入`Notify.vue`组件,并通过`install`方法中注入的Vue来完成功能。实例挂载之后才可以访问`$el`选项,可以通过`Vue.use`来使用插件,然后在App.vue中验证功能是否正常。要实现传入模板并且显示出来,可以通过`$mount` API手动挂载一个实例,并在调用`$notify`方法时将挂载的元素插入到文档中。通过创建Vue组件,将DOM、JS、Style都创建好,最后调用`$notify`方法将组件插入到页面中。要实现传入模板,可以使用`v-html`指令来插入模板,并在Notify.vue中新增接收参数的方法。在App.vue中传递一段模板,页面上操作的效果为显示提示框,两秒后消失。
手写一个简单的谷歌浏览器拓展插件(附github源码)
手写谷歌浏览器插件教程:简易实现与代码详解
首先,让我们通过一个直观的示例来启动创建过程。点击浏览器地址栏输入 chrome://extensions/,即可直接访问扩展程序管理界面。 核心配置文件是 manifest.json,这个文件记录了插件的safari 查看源码基本信息,如名称、描述、权限等,是插件身份的身份证。 当插件被激活时,用户会看到一个弹出层,这是通过编写 popup.html 来实现的,它包含了一个简单的HTML界面,用于交互或显示信息。 为了保持代码的清晰,我们把相关的脚本逻辑分离到单独的 popup.js 文件中,这样也支持使用 script 标签直接嵌入。在该文件中,我们将实现插件的核心功能。 此外,我们还需要一个辅助文件 inject.js,它的任务是将特定的代码注入到目标网页,实现所需功能,如上图所示。 整个项目的目录结构清晰可见,便于管理和维护。但这里只是基础部分,更多功能的实现和优化将在后续篇章中详细介绍。mybatis插件机制源码解析
引言
本篇源码解析基于MyBatis3.5.8版本。
首先需要说明的是,本篇文章不是mybatis插件开发的教程,而是从源码层面分析mybatis是如何支持用户自定义插件开发的。
mybatis的插件机制,让其扩展能力大大增加。cloudstack源码学习比如我们项目中经常用到的PageHelper,这就是一款基于mybatis插件能力开发的产品,它的功能是让基于mybatis的数据库分页查询更容易使用。
当然基于插件我们还可以开发其它功能,比如在执行sql前打印日志、做权限控制等。
正文mybatis插件也叫mybatis拦截器,它支持从方法级别对mybatis进行拦截。整体架构图如下:
解释下几个相关概念:
Interceptor拦截器接口,用户自定义的拦截器就是实现该接口。
InterceptorChain拦截器链,其内部维护一个interceptorslist,表示拦截器链中所有的拦截器,并提供增加或获取拦截器链的方法。比如有个核心的方法是pluginAll。该方法用来生成代理对象。
Invocation拦截器执行时的上下文环境,其实就是目标方法的调用信息,包含目标对象、调用的方法信息、参数信息。核心方法是proceed。该方法的主要目的就是进行处理链的传播,执行完拦截器的方法后,最终需要调用目标方法的invoke方法。
mybatis支持在哪些地方进行拦截呢?你只需要在代码里搜索interceptorChain.pluginAll的使用位置就可以获取答案,一共有四处:
parameterHandler=(ParameterHandler)interceptorChain.pluginAll(parameterHandler);resultSetHandler=(ResultSetHandler)interceptorChain.pluginAll(resultSetHandler);statementHandler=(StatementHandler)interceptorChain.pluginAll(statementHandler);executor=(Executor)interceptorChain.pluginAll(executor);这四处实现的原理都是一样的,我们只需要选择一个进行分析就可以了。
我们先来看下自定义的插件是如何加载进来的,比如我们使用PageHelper插件,arp 全部源码通常会在mybatis-config.xml中加入如下的配置:
<plugins><plugininterceptor="com.github.pagehelper.PageInterceptor"><!--configparamsasthefollowing--><propertyname="param1"value="value1"/></plugin></plugins>mybatis在创建SqlSessionFactory的时候会加载配置文件,
publicConfigurationparse(){ if(parsed){ thrownewBuilderException("EachXMLConfigBuildercanonlybeusedonce.");}parsed=true;parseConfiguration(parser.evalNode("/configuration"));returnconfiguration;}parseConfiguration方法会加载包括plugins在内的很多配置,
privatevoidparseConfiguration(XNoderoot){ try{ ...pluginElement(root.evalNode("plugins"));...}catch(Exceptione){ thrownewBuilderException("ErrorparsingSQLMapperConfiguration.Cause:"+e,e);}}privatevoidpluginElement(XNodeparent)throwsException{ if(parent!=null){ for(XNodechild:parent.getChildren()){ Stringinterceptor=child.getStringAttribute("interceptor");Propertiesproperties=child.getChildrenAsProperties();InterceptorinterceptorInstance=(Interceptor)resolveClass(interceptor).getDeclaredConstructor().newInstance();interceptorInstance.setProperties(properties);configuration.addInterceptor(interceptorInstance);}}}pluginElement干了几件事情:
创建Interceptor实例
设置实例的属性变量
添加到Configuration的interceptorChain拦截器链中
mybatis的插件是通过动态代理实现的,那肯定要生成代理对象,生成的逻辑就是前面提到的pluginAll方法,比如对于Executor生成代理对象就是,
executor=(Executor)interceptorChain.pluginAll(executor);接着看pluginAll方法,
/***该方法会遍历用户定义的插件实现类(Interceptor),并调用Interceptor的plugin方法,对target进行插件化处理,*即我们在实现自定义的Interceptor方法时,在plugin中需要根据自己的逻辑,对目标对象进行包装(代理),创建代理对象,*那我们就可以在该方法中使用Plugin#wrap来创建代理类。*/publicObjectpluginAll(Objecttarget){ for(Interceptorinterceptor:interceptors){ target=interceptor.plugin(target);}returntarget;}这里遍历所有我们定义的拦截器,调用拦截器的plugin方法生成代理对象。有人可能有疑问:如果有多个拦截器,target不是被覆盖了吗?
其实不会,所以如果有多个拦截器的话,生成的代理对象会被另一个代理对象代理,从而形成一个代理链条,执行的时候,依次执行所有拦截器的拦截逻辑代码。
plugin方法是接口Interceptor的默认实现类,
defaultObjectplugin(Objecttarget){ returnPlugin.wrap(target,this);}然后进入org.apache.ibatis.plugin.Plugin#wrap,
publicstaticObjectwrap(Objecttarget,Interceptorinterceptor){ Map<Class<?>,Set<Method>>signatureMap=getSignatureMap(interceptor);Class<?>type=target.getClass();Class<?>[]interfaces=getAllInterfaces(type,signatureMap);if(interfaces.length>0){ returnProxy.newProxyInstance(type.getClassLoader(),interfaces,newPlugin(target,interceptor,signatureMap));}returntarget;}首先是获取我们自己实现的Interceptor的方法签名映射表。然后获取需要代理的对象的Class上声明的所有接口。比如如果我们wrap的是Executor,就是Executor的所有接口。然后就是最关键的一步,用Proxy类创建一个代理对象(newProxyInstance)。
注意,newProxyInstance方法的第三个参数,接收的是一个InvocationHandler对象,表示的是当动态代理对象调用方法的时候会关联到哪一个InvocationHandler对象上,并最终由其调用。
我们这里传入的是Plugin类,故在动态运行过程中会执行Plugin的invoker方法。
如果对这一段不是很理解,建议先了解下java动态代理的原理。java动态代理机制中有两个重要的角色:InvocationHandler(接口)和Proxy(类),这个是背景知识需要掌握的。
我们在深入看下上面的getSignatureMap方法,
privatestaticMap<Class<?>,Set<Method>>getSignatureMap(Interceptorinterceptor){ //从Interceptor的类上获取Intercepts注解,说明我们自定义拦截器需要带注解InterceptsinterceptsAnnotation=interceptor.getClass().getAnnotation(Intercepts.class);//issue#if(interceptsAnnotation==null){ thrownewPluginException("No@Interceptsannotationwasfoundininterceptor"+interceptor.getClass().getName());}Signature[]sigs=interceptsAnnotation.value();Map<Class<?>,Set<Method>>signatureMap=newHashMap<>();//解析Interceptor的values属性(Signature[])数组,存入HashMap,Set<Method>>for(Signaturesig:sigs){ Set<Method>methods=MapUtil.computeIfAbsent(signatureMap,sig.type(),k->newHashSet<>());try{ Methodmethod=sig.type().getMethod(sig.method(),sig.args());methods.add(method);}catch(NoSuchMethodExceptione){ thrownewPluginException("Couldnotfindmethodon"+sig.type()+"named"+sig.method()+".Cause:"+e,e);}}returnsignatureMap;}首先需要从Interceptor的类上获取Intercepts注解,说明我们自定义拦截器需要带注解,比如PageHelper插件的定义如下:
<plugins><plugininterceptor="com.github.pagehelper.PageInterceptor"><!--configparamsasthefollowing--><propertyname="param1"value="value1"/></plugin></plugins>0所以我们可以知道,getSignatureMap其实就是拿到我们自定义拦截器声明需要拦截的类以及类对应的方法。
前面说过,当我们调用代理对象时,最终会执行Plugin类的invoker方法,我们看下Plugin的invoker方法,
<plugins><plugininterceptor="com.github.pagehelper.PageInterceptor"><!--configparamsasthefollowing--><propertyname="param1"value="value1"/></plugin></plugins>1Interceptor接口的intercept方法就是我们自定义拦截器需要实现的逻辑,其参数为Invocation,可从Invocation参数中拿到执行方法的对象,方法,方法参数,比如我们可以从statementHandler拿到SQL语句,实现自己的特殊逻辑。
在该方法的结束需要调用invocation#proceed()方法,进行拦截器链的传播。
参考:
blogs.com/chenpi/p/.html
电脑上最好用的速记工具
葫芦笔记的uTools插件,一款适用于Mac、Windows、Linux的速记插件,其源码地址为:github.com/fishyer/utools-plugin-flomo。之所以选择葫芦笔记而非Flomo,主要基于两个原因。 通过访问我的葫芦笔记邀请链接进行注册,您和我都将获得个积分,相当于按专业版价格计算的约6元价值。 如果您对编程感兴趣,想要学习并自行开发插件、云服务、脚本、网站或app,可参考以下资源:我最近创建了一个针对零基础学习者的编程入门群,每周更新一期视频教程。 使用葫芦笔记uTools插件的方法包括:设置葫芦笔记API。
利用uTools,选择"发送文字到葫芦笔记"功能,即可将任意复制的文字记录到每日笔记中。
弹出快速编辑框,输入文字后按回车键,实现快速记录。
此外,为了更好地利用葫芦笔记uTools插件,可参考以下技巧和安装指南。 在使用过程中,如需进一步信息或支持,可查阅相关参考资料。UEC++插件开发笔记
本文旨在概述C++在UE插件开发中的应用,主要聚焦于Actor实现和菜单扩展功能。UE插件开发流程简明,创建Actor文件在插件窗口即可完成。以FacePlayerActor为例,实现每帧向当前角色方向旋转,达到特定效果。插件文件分为.h和.cpp两部分,分别用于定义类和实现函数。
在菜单编辑中,需加入slate和slatecore类以扩展功能。通过继承插件模块接口并在.h文件中定义,确保.cs文件中依赖这些类。初始化模块后,实现菜单扩展,定义菜单名称、提示,以及点击响应函数。回调函数中,菜单1执行打印LOG操作,菜单2在此基础上加入子菜单,实现更复杂的功能。
对于在菜单栏加入同级菜单,通过pulldown函数实现,设置标题、说明文字和子菜单或函数。MyPlugin.h和MyPlugin.cpp源代码文件分别包含模块定义和具体实现,展示整个菜单扩展的完整流程。
掌控自己的内容:使用 Obsidian 打造个人知识管理系统(三):必备插件安装
继续你的知识管理之旅,让我们深入探讨如何在Obsidian中安装和利用关键插件,让你的个人知识库更加强大。首先,确保Obsidian处于非安全模式,然后进入插件安装界面,如下所示。附件管理插件
为了轻松管理外部文件,附件管理插件允许你直接复制并整合和各类文件到指定文件夹,配置过程直观明了,如图所示。File Tree Alternative Plugin
Obsidian默认的文件浏览器可能不支持显示所有文件类型,File Tree Alternative插件就派上用场了,它可以显示隐藏的Word或Excel文件,如图所示,即使你对显示与否有严格要求,也可选择安装。File Explorer Note Count
这个插件为文件浏览器添加了笔记数量计数功能,安装后,你的笔记管理将更加有序,如图呈现。Quiet Outline
安装Quiet Outline后,大纲视图将更加清晰,让你对笔记结构一目了然,如图所示。Editing Toolbar
编辑器工具栏插件增添了更多编辑便利,安装后,编辑体验提升,如图所示。Image Toolkit
浏览插件让你在编辑时能轻松预览和操作,安装后,编辑工作更顺畅,如图可见。Annotator
PDF注释爱好者可以借助Annotator,安装后,注释功能强大,只需在笔记源码中添加特定标记,如图所示。Link Embed
Link Embed允许你将超链接无缝嵌入笔记,提升阅读效率,如图所示。Local Rest API
配合浏览器插件,你可以轻松将网页内容导入笔记,只需设置对应Key,如图所示。 通过以上插件的安装和配置,你的Obsidian知识管理系统将更加完善。要想了解更多搭建个人笔记库的详细步骤,持续关注我们的知乎专栏,解锁更多实用技巧。