1.mybatis插件机制源码解析
2.「安卓按键精灵」扒别人脚本的插件插件界面源码
3.Vue—关于插件(源码级别的插件分析+实践)
4.如果在开发项目中,一个插件用了两次,源码源码修改bug时要改插件的泄漏泄漏源码该怎么办?
5.SpringBoot 玩一玩代码混淆,防止反编译代码泄露
6.《刀塔传奇》百度贴吧爆出私服信息 疑游戏源代码泄漏
mybatis插件机制源码解析
引言
本篇源码解析基于MyBatis3.5.8版本。什意思
首先需要说明的插件插件是,本篇文章不是源码源码超准顶底源码mybatis插件开发的教程,而是泄漏泄漏从源码层面分析mybatis是如何支持用户自定义插件开发的。
mybatis的什意思插件机制,让其扩展能力大大增加。插件插件比如我们项目中经常用到的源码源码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插件,通常会在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
「安卓按键精灵」扒别人脚本的界面源码
在一次技术交流中,有朋友向我咨询如何解析别人的在线书城设计源码安卓脚本界面源码,我虽不擅长直接破解,但分享一下如何通过常规手段揭开这一层神秘面纱。
界面的代码其实并不复杂,主要由几个基础元素构成,模仿起来并不困难。不过,这里我们不走寻常路,而是要深入探究其背后的逻辑和文件结构。
要找到界面代码,首先需要进入脚本的安装目录,通常在"/data/data/"后面跟随应用的包名。打开这个目录,找到其中的"files"文件夹,这个文件夹往往是保存应用界面配置的地方,基于以往的经验,我们先一探究竟。
在一堆与脚本相关的文件中,我们使用文本读取命令逐一探索。代码逻辑是逐个读取文件内容,比如当我们看到script.cfg文件,它虽与界面截图对应,但并非源码,只是记录了用户填写内容的配置信息。
在遍历的输出结果中,我注意到一行标注为"script.uip"的文件。从后缀名判断,这可能是与UI界面相关的。更有趣的是,它包含了一些花括号{ },这提示了我们可能找到了界面源码的线索。
接着,我们面对的是可能存在的乱码问题。按键的乱码可能是加密或编码问题,通过观察问号,武侠乂ID源码猜测是编码错误。编码为utf8的按键支持广泛,我们尝试用转码插件来解决这个问题,以gbk编码为例进行测试,结果出乎意料地顺利。
解决乱码后,我们将调试结果复制到文本中,确认这就是我们寻找的界面源码。将其粘贴回脚本中,界面效果依然保持完好。
但别忘了,包名这一关键信息可能需要用户自行获取。在运行脚本时,可以在界面上找到包名。为了简化操作,我们可以在脚本中直接引入包名,跳过遍历,直接读取界面文件。
至此,我们已经完成了从头到尾的解析过程,代码也变得更加简洁有效。如果你对这些内容感兴趣,不妨试着操作一番,或许会有所收获。
当然,如果你在探索过程中遇到任何问题,或者想要了解更多关于按键精灵的资源,别忘了关注我们的论坛、知乎账号以及微信公众号"按键精灵",那里有更全面的教程和讨论。
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工程,在`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中传递一段模板,页面上操作的效果为显示提示框,两秒后消失。
如果在开发项目中,一个插件用了两次,修改bug时要改插件的源码该怎么办?
第一种是面向过程思想写的分页插件中的代码,第二种是面向对象思想写的分页插件中的代码,思想不同,但改的两种方法都同时适用以上的分页插件!改插件最主要是看懂它的思路,然后顺其自然就很容易了!ps:建议看不懂的以后可以多打开各种插件和框架源码看,多思考,相信你会学到更多
SpringBoot 玩一玩代码混淆,防止反编译代码泄露
编译过程将源代码转换为机器可读的格式,形成 .class 文件。然而,面对反编译工具,如 JD-GUI,开发者可能担心自己的代码会暴露给他人。这时,代码混淆成为了一种有效的防御手段。混淆代码的目标是使反编译变得困难,甚至无法解读原始代码逻辑。
实现混淆的步骤包括:首先,在项目路径下创建一个 proguard.cfg 文件,用于配置哪些类、方法和枚举需要保留,以及哪些不需要混淆。该文件包含了一系列的规则,以确保代码的结构和逻辑不会被完全破坏。其次,在项目的 pom 文件中添加 ProGuard 混淆插件,以便在构建过程中应用这些规则。在构建配置中,需要指定混淆规则文件的路径。
完成配置后,只需执行正常的构建流程。当构建完成后,生成的 jar 包将包含经过混淆的代码。此时,即便是使用反编译工具,也无法轻易地解读出原始的代码结构和逻辑,从而保护了开发者的知识产权。
总结而言,代码混淆是保护代码不被反编译的一种方法。通过合理配置混淆规则和插件,开发者可以在不改变代码功能的前提下,增加代码的可读性和理解难度,为防止代码泄露提供了额外的安全屏障。
《刀塔传奇》百度贴吧爆出私服信息 疑游戏源代码泄漏
惊人发现《刀塔传奇》贴吧惊现私服泄露疑云 1月日,一场震撼游戏界的风波在《刀塔传奇》百度贴吧悄然掀起。日晚,贴吧突然充斥着“刀塔私服”的消息,贴吧吧主权限被百度暂时冻结,导致不良信息无法及时清理。直至今日凌晨,官方才得以恢复管理,开始了对贴吧内信息的全面清理。龙图游戏对此迅速行动,发布公告,坚称已向警方报案,警方已介入调查,此事绝不容小觑。 私服消息中透露,下载的私服游戏提供了官方难以企及的诱惑,如金币和经验大幅增多,充值升级快速,技能冷却时间缩短。贴吧玩家纷纷指出,私服与官方版本在画面和玩法上的相似性,让人不禁怀疑是否源代码已遭泄露。然而,业内人士认为,《刀塔传奇》用户群体已相当稳固,大R用户投入大量时间和金钱,社交网络紧密,私服虽有吸引力,但龙图游戏对中小R的扶持力度大,且私服的非法性和不稳定性使其难以撼动官方的地位。 然而,私服的危险性不容忽视。它们通常包含恶意插件,可能会窃取玩家个人信息,篡改系统设置,甚至导致银行卡被盗、账号信息泄露,带来不可挽回的经济损失。腾讯游戏频道郑重警告,下载私服不仅会威胁到财产安全,法律保障也将荡然无存。因此,玩家们务必保持警惕,切勿轻信非官方信息。 龙图游戏针对这一“非法私服”事件发布了官方声明: 我们注意到《刀塔传奇》论坛及玩家群体中,“私服”谣言肆虐。这些私服是由不法分子非法运营,安装文件潜藏恶意插件,会窃取玩家信息,破坏游戏平衡,严重侵犯玩家权益。我们已向警方报案,将坚决打击这种非法行为。在此,我们再次呼吁玩家,远离非法私服,保护您的账号安全,谨防财产损失。 龙图游戏,坚守正版游戏的尊严,维护玩家权益,保障游戏环境的和谐稳定。让我们共同期待警方的调查结果,以揭示这起事件的真相。 年1月日