当前位置:首页 > 时尚生活

returning 性能优化,还得看AspectJ

最近,在纽约证券交易所上市一年后,中国电动汽车初创公司威来似乎遇到了麻烦。第二季度财报显示,由于旗舰电动车ES8销量大幅下滑,公司2019年第二季度亏损4.79亿美元,仅实现收入2.2亿美元。

这篇文章来自verymrq的提交,分享了AspectJ的相关知识,AspectJ是性能优化的产物。相信会对大家有帮助!同时也感谢作者精彩的文章。

verymrq的博客地址:

https://me.csdn.net/verymrq

/ AOP /

面向方面编程。

如果OOP把问题分成单个模块,AOP统一管理某一类涉及多个模块的问题。比如登录、传输、大文件上传三个模块。现在,有必要添加性能测试功能来计算这三个模块各花费多少时间。

OOP思想是设计一个性能检测模块,提供这三个模块调用的接口。这样,每个模块都应该调用性能测试模块的接口。如果改变接口,需要在每次调用这三个模块的地方进行修改。

AOP的思想是在特定的切入点挂接这些独立的模块,在不影响原有模块独立性的情况下,给模块增加共同的逻辑。

所以,这就是我上面说的:统一管理某一类涉及多个模块的问题。

安卓AOP三剑客:APT,AspectJ,Javassist。

APT应用:Dagger,butterKnife,组件化方案等等AspectJ:主要用于性能监控,日志埋点等Javassist:热更新(可以在编译后,打包Dex之前干事情,可以突破一下限制)

/ AspectJ /

AspectJ是今天的主角,主要用在不想侵犯原代码的场景中。比如SDK需要在不入侵的情况下向主机中插入一些代码,进行日志记录、性能监控、动态权限控制,甚至代码调试。

访问说明

首先,您需要在项目根目录的build.gradle中添加依赖项:

构建{

仓库{

共享

}

依赖项{

class path ' com . Android . tools . build:gradle:2 . 3 . 0-beta 2 '

类路径' com . Hu Jiang . aspectjx:gradle-Android-plugin-aspectjx:2 . 0 . 6 '

}

}

然后将AspectJ依赖项添加到主项目或库的build.gradle中:

compile ' org . AspectJ:AspectJ rt:1 . 8 . 9 '

同时,添加AspectJX模块进行build.gradle:

应用插件:' android-aspectjx '

这样就配置好了Android Studio中AspectJ的环境。如果在编译过程中遇到“无法确定缺失类型xxxxx的超类”等错误,请参考项目自述文件中excludeJarFilter的使用。

aspectjx {

//包含您想要编制的libs

包括图像过滤器'通用图像加载器',' AspectJX-演示/库'

//不包括您不想编制的lib

排除图像过滤器'通用图像加载器'

}

基本用途

直接看代码,在活动:

@覆盖

protected void oncreate(@ Nullable Bundle savedInstanceState){

super . OnCreate(SaveDinstancestate);

testMethod

}

privatevoidtestMethod{

Log.e(DemoAspect。标签,“TestMethod-invoke”);

}

创建新的DemoAspect类:

@方面

publicclassDemoAspect{

publicationstatifinString TAG = " DeMoaspect ";

@ Before(" execution(* com . Hu Jiang . library . demo . demo activity . test *(..))")

publicvoidtestAspectBefore(连接点){

Log.e(TAG,point . GetSignature . GetName+"-before ");

}

}

运行时打印:

test method-before com . hujiang . library . demo E/demo aspect:test method-invoke

为了完成插入操作,我们只需要

类上加入注释@Aspect方法上加入注释@BeforeBefore里写入要插入的相关信息

很简单吗?下面详细解释一下。

建议

也就是说,要插入的代码是如何插入的,就是方法上的注释。

前后都很好理解,上面的例子已经说的很清楚了。

返回后

适用于需要获取返回值的情况,如:

privateintAfterReturningTest {

Log.e(DemoAspect。标签,“after returning-invoke”);

返回10;

}

@ after returning(value = " execution(* com . hujiang . library . demo . demo activity . after returning *(..))",返回= "num ")

public void testaspectafterreturning(int num){

Log.e(TAG," after returning-num:"+num);

}

这样就可以在cut方法中得到返回值。值得注意的是,方法参数必须与注释中的值一致。

【returning = "num"】===【intnum】

事后

适用于收集和监控异常信息。

privatevoidAfterThrowingTest {

视图v = null

设置可见性(视图。VISIble);

}

@ AFTERROWwing(value = " execution(* com . Hu Jiang . library . demo . demo activity . AFTERROWwing *(..))”,抛出=“异常”)

publicationvoutestaspectafterreturning(异常异常){

Log.e(TAG," after hrowing-exception:"+exception . getmessage);

}

同样,参数和注释中的值必须一致。崩溃也会在这里发生,不会因为切片操作而直接被捕获,只会在抛出异常之前打印异常信息。

围绕

可以在方法执行前后调用,更加灵活。

privatevoidAroundTest{

Log.e(DemoAspect。标签,“around test-invoke”);

}

@ about(" execution(* com . hujiang . library . demo . demo activity . Around test(..))")

public void testaspectround(proceedingjoint point)throws throwable {

Log.e(TAG,point . GetSignature . GetName+"-before ");

继续;

Log.e(TAG,point . GetSignature . GetName+"-after ");

}

原方法通过执行ProceedingJoinPoint的Proceeding方法调用,控件灵活。如果你愿意,可以不调用就截取。

切入点

告诉代码注入工具在哪里注入特定代码段的表达式。也就是例子中的这句话:

@ Before(" execution(* com . Hu Jiang . library . demo . demo activity . test *(..))")

我们分成几个部分依次来看:

@ before: advice,也就是具体的插入点,我们已经介绍过了

执行:处理连接点的类型,如调用、执行和代码内

其中,调用和执行是类似的,也就是插入代码。不同的是执行是在切入方法中,调用是在调用切入方法之前或者之后。

//通话:

呼叫(之前)

切入点{

切入点方法

}

呼叫(之后)

//执行:

切入点{

执行(之前)

切入点方法

执行(之后)

}

Withcode通常用于过滤一些切入条件,以实现更精确的切入控制,例如:

@覆盖

受保护的无效创建(捆绑保存的实例){

super . OnCreate(SaveDinstancestate);

setContentView(r . layout . activity _ main);

test1

test2

}

publicvoidtest{

Log.e("丘云飞"," test ");

}

publicvoidtest1{

测试;

}

publicvoidtest2{

测试;

}

如果我们想剪切测试方法,但只想在test2中调用test来执行剪切方法,我们需要使用withincode。

//在测试方法中

@ Pointcut(" within code(* com . Hu Jiang . library . aspect . main activity . test2(..))")

publicvoidinvoke2{

}

//调用测试方法时

@ Pointcut(" call(* com . Hu Jiang . library . aspect . main activity . test(..))")

publicvoidinvoke{

}

//同时满足前面的条件,即在切入之前在test2方法中调用测试方法

@切入点(“调用& amp& ampinvoke2”)

publicationvoinvokeaonly 2 {

}

@ Before(" invoke only 2 ")

publicationvotybeforeivokeonly 2(连接点连接点){

string key = join point . GetSignature . tostring;

Log.d(TAG," BeforeInvokOnly 2:"+key);

}

MethodPattern:这是最重要的表达式,大概:@ comment和access right,返回值类型和包名。函数名(参数)

@注释和访问权限(public/private/protect和static/final):它们是可选的。如果没有设置,默认情况下都是选中的。以访问权限为例。如果未将访问权限设置为条件,将搜索公共、私有、保护、静态和最终功能。

返回值类型:是普通函数的返回值类型。如果类型不受限制,则用*通配符表示。

包名。函数名:用于查找匹配的函数。可以使用通配符,包括and …和+。其中该符号用于匹配除。,而...表示任何包,符号+表示子类。

* com . Hu Jiang . library . demo . demo activity . test *(..)

第一部分:“”表示返回值,“”表示返回值为任意类型。

第二部分:是典型的包名路径,可以包含""进行一般分配,几个" "没有区别。在「时间」,你可以使用「&:& amp;、||、! "结合各种条件。类似于[test*]的写法,是指任何方法名称以test开头的方法。

第三部分:表示这个方法的参数,可以指定类型,比如android.os.Bundle,或者(…)表示任意类型任意个数的参数,也可以混合编写(android.os.Bundle,…)表示第一个参数为Bundle,以下可选。

自定义切入点:有时候需要指定哪些方法需要AOP操作,目标明确,也可以通过标注来完成。先声明评论:

@Retention(保留策略。班级)

@Target({ElementType。方法,元素类型。类型})

public @ InterfaceSpectannotation {

}

然后在切片类中定义它:

//使用这个注释定义一个切入点

@ Pointcut(" execution(@ com . Hu Jiang . library . aspect . aspectannotation * *(..))")

publicationvotyaspectannotation {

}

@Before("AspectAnnotation ")

publicvoidtestAspectAnnotation(连接点){

Log.e(TAG,point . getsignature . getname+"-Before ");

}

//用于活动

@覆盖

protected void oncreate(@ Nullable Bundle savedInstanceState){

super . OnCreate(SaveDinstancestate);

注释测试;

}

@ AspectannoStation

privatevoidAnnotationTest{

Log.e(DemoAspect。TAG," AnnotationTest-invoke ");

}

很好用,MethodPattern之前也有介绍,所以这里不能省略@这个注释。

/AspectJ实战/

实施登录检查操作

很多应用都有这个要求,操作前提醒用户注册登录,跳转到注册或登录界面,如果用AspectJ实现的话,非常简洁无创。

privateStaticFinaliString TAG = " AspectCommonTool ";

@ Pointcut(" execution(@ XXX . AspectJ . annotation . NeedLogon * *(..))")

publicvoidneedLoginMethod{

}

/**

*插入@ NeedLogin方法

*如果在非活动中使用@ NeedLogin,则必须将参数作为跳转开始页传递到上下文中

*/

@周围(“需求方法”)

public void connected loginaround(proceedingjointpoint proceedingjointpoint)throws可浏览{

mContext = null

///proceedingjointpoint . getthis可以获取调用此方法的对象

if(proceedingjointpoint . getthiinstancefcontext){

mccontext =(Context)proceedingjointpoint . getthis;

} else{

///proceedingjointpoint . getargs可以获取方法的所有参数

for(对象上下文:proceedingjointpoint . getargs){

if(上下文实例上下文){

mContext =(Context)Context;

打破;

}

}

}

if(McContext = = null){

返回;

}

if(LoginUtils.isLogin) {

/**

*如果用户登录,执行原始方法

*/

proceedingJoinPoint.proceed .继续;

} else{

/**

*不登录跳转到登录注册主界面

*/

}

使用方便,无创,后期维护容易。可以实现类似的思路:查看网络状态、查看权限状态、避免多次点击按钮、自动完成缓存等。

性能监控

其实AspectJ在Android中的应用主要集中在性能监控、日志嵌入等方面。下面是一个简单的例子:

我们监控布局加载时间,判断布局是否嵌套过多或复制过多,导致活动开始堵塞。首先,我们知道活动通过设置内容视图方法加载布局:

布局解析过程,IO过程创建View为反射过程

这两个步骤都是耗时的操作,所以我们需要监控setContentView。

@ about(" execution(* Android . app . Activity . SetContentView(..))")

publicationgetcontentviewtime(proceedingjoint point)throws throwable {

string name = point . GetSignature . ToshortString;

long time = system . CurrentiMemillis;

继续;

Log.e(TAG,name+" cost:"+(System . CurrentiMemillis-time));

}

//活动

publicClassDemoactivityExtendsAppCompactivity {

@覆盖

protected void oncreate(@ Nullable Bundle savedInstanceState){

super . OnCreate(SaveDinstancestate);

setContentView(r . layout . activity _ main);

}

}

按如下方式打印日志:

demo aspect:AppCompactivity . SetContentView(..)成本:76

在日常开发中,我们可以将时间上传到服务器,收集用户信息,找到Caton Activity,进行相应的优化。

当然,这是一个非常简单的实现,您也可以在实际开发中监控您想要监控的各种位置。

1.《returning 性能优化,还得看AspectJ》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。

2.《returning 性能优化,还得看AspectJ》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。

3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/shehui/1085691.html

上一篇

房客退租满屋垃圾 登上网络热搜了!

下一篇

造物法则2先锋英雄 造物法则2先锋英雄:新玩法上线!银月讨伐来袭

淘货源批发 开淘宝店找货源的九种方法,总有一种适合你

淘货源批发 开淘宝店找货源的九种方法,总有一种适合你

刚入行的小卖家可能没有意识到产品的重要性。以为可以直通车,可以优化,可以掌握各种秘籍,可以把任何一个宝都推成爆款,其实忽略了销售的本质。 反之,如果有货源好,性价比高,宝贝,那就推舟。小卖家最头疼的就是如何找到好的货源。这次主要说找哪些渠道。 首先,寄售 这是最常见最简单的。百度搜索很多,门...

速算24点的小窍门 纸牌游戏24点的规则和方法分享

速算24点的小窍门 纸牌游戏24点的规则和方法分享

24点算法是一种棋牌数学休闲益智游戏,将四张扑克牌的数字相加、相减、相乘、相除(包括括号)使计算结果等于24。这个小游戏可以训练人的快速反应能力。除了平时的休闲娱乐之外,它在数学课堂教学或数学周的小竞赛中经常被许多老师使用,因为它可以极大地调动学生各种感官的协调能力,非常有利于培养学生的心算...

便秘怎么办快速排便的方法 大便硬、拉不出,便秘怎么办?这些日常方法有助你快速排便~

  • 便秘怎么办快速排便的方法 大便硬、拉不出,便秘怎么办?这些日常方法有助你快速排便~
  • 便秘怎么办快速排便的方法 大便硬、拉不出,便秘怎么办?这些日常方法有助你快速排便~
  • 便秘怎么办快速排便的方法 大便硬、拉不出,便秘怎么办?这些日常方法有助你快速排便~

字体安装方法 电脑字体快速安装删除管理的方法

  • 字体安装方法 电脑字体快速安装删除管理的方法
  • 字体安装方法 电脑字体快速安装删除管理的方法
  • 字体安装方法 电脑字体快速安装删除管理的方法

搜图 以图搜图的方法,不管你能不能找到,反正我能!

  • 搜图 以图搜图的方法,不管你能不能找到,反正我能!
  • 搜图 以图搜图的方法,不管你能不能找到,反正我能!
  • 搜图 以图搜图的方法,不管你能不能找到,反正我能!

意大利翻译 意大利语怎么翻译成英文?这三个方法简单又实用

  • 意大利翻译 意大利语怎么翻译成英文?这三个方法简单又实用
  • 意大利翻译 意大利语怎么翻译成英文?这三个方法简单又实用
  • 意大利翻译 意大利语怎么翻译成英文?这三个方法简单又实用

瘊子的最佳治疗方法 治疗寻常疣这三种方法最好不要选!

  • 瘊子的最佳治疗方法 治疗寻常疣这三种方法最好不要选!
  • 瘊子的最佳治疗方法 治疗寻常疣这三种方法最好不要选!
  • 瘊子的最佳治疗方法 治疗寻常疣这三种方法最好不要选!

starnet 值得收藏!基于激光雷达数据的深度学习目标检测方法大合集(下)

  • starnet 值得收藏!基于激光雷达数据的深度学习目标检测方法大合集(下)
  • starnet 值得收藏!基于激光雷达数据的深度学习目标检测方法大合集(下)
  • starnet 值得收藏!基于激光雷达数据的深度学习目标检测方法大合集(下)