日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

android aspectj 参数,AspectJ在Android中的使用

發(fā)布時(shí)間:2023/12/20 Android 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android aspectj 参数,AspectJ在Android中的使用 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、AOP

全稱“Aspect Oriented Programming”,面向切面編程,由于面向?qū)ο蟮乃枷胍蟾邇?nèi)聚,低耦合的風(fēng)格,使模塊代碼間的可見(jiàn)性變差,對(duì)于埋點(diǎn),日志輸出等需求,就會(huì)變的十分復(fù)雜,如果手動(dòng)編寫代碼,入侵性很大,不利于擴(kuò)展,AOP應(yīng)運(yùn)而生。

二、使用場(chǎng)景

當(dāng)我們需要在某個(gè)方法運(yùn)行前和運(yùn)行后做一些處理時(shí),便可使用AOP技術(shù)。具體有:

統(tǒng)計(jì)埋點(diǎn)

日志打印/打點(diǎn)

數(shù)據(jù)校驗(yàn)

行為攔截

性能監(jiān)控

動(dòng)態(tài)權(quán)限控制

***三、環(huán)境配置

我們以Android工程+官方的AspectJ為例

1.項(xiàng)目根目錄build.gradle配置

dependencies {

classpath 'org.aspectj:aspectjtools:1.8.9'

classpath 'org.aspectj:aspectjweaver:1.8.9'

}

2.具體使用AspectJ的工程build.gradle中配置

dependencies {

implementation 'org.aspectj:aspectjrt:1.8.13'

}

import org.aspectj.bridge.IMessage

import org.aspectj.bridge.MessageHandler

import org.aspectj.tools.ajc.Main

final def log = project.logger

final def variants = project.android.applicationVariants

variants.all { variant ->

if (!variant.buildType.isDebuggable()) {

log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.")

return;

}

JavaCompile javaCompile = variant.javaCompile

javaCompile.doLast {

String[] args = ["-showWeaveInfo",

"-1.8",

"-inpath", javaCompile.destinationDir.toString(),

"-aspectpath", javaCompile.classpath.asPath,

"-d", javaCompile.destinationDir.toString(),

"-classpath", javaCompile.classpath.asPath,

"-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)]

log.debug "ajc args: " + Arrays.toString(args)

MessageHandler handler = new MessageHandler(true);

new Main().run(args, handler);

for (IMessage message : handler.getMessages(null, true)) {

switch (message.getKind()) {

case IMessage.ABORT:

case IMessage.ERROR:

case IMessage.FAIL:

log.error message.message, message.thrown

break;

case IMessage.WARNING:

log.warn message.message, message.thrown

break;

case IMessage.INFO:

log.info message.message, message.thrown

break;

case IMessage.DEBUG:

log.debug message.message, message.thrown

break;

}

}

}

}

以上配置完成后,便可以項(xiàng)目中進(jìn)行使用了,當(dāng)然,除了官方提供的,還有其他三方的aspectJ框架供我們使用,如https://github.com/HujiangTechnology/gradle_plugin_android_aspectjx,其配置與上面的略有不同,開(kāi)發(fā)者根據(jù)自己選擇的具體框架進(jìn)行相應(yīng)的配置

三、代碼實(shí)例

public class AspectJActivity extends AppCompatActivity {

private String TAG = "AspectJActivity";

@Override

protected void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_aspect);

Log.i(TAG,hashCode()+"");

aspectTest();//以普通方法進(jìn)行aspectJ處理

aspectTestAnn();//以注解方式進(jìn)行

}

public void aspectTest() {

Log.i(TAG, "aspect test");

}

@AspectAnn

public void aspectTestAnn() {

Log.i(TAG, "aspect by annoation test");

}

}

要求,在運(yùn)行aspectTest()前先打印一個(gè)信息,在運(yùn)行aspectTestAnn后也打印一個(gè)信息,兩者最大的區(qū)別在于,前者使用類名和方法名來(lái)實(shí)現(xiàn)切面,而后者則使用注解來(lái)實(shí)現(xiàn),在實(shí)際開(kāi)發(fā)中,用注解來(lái)實(shí)現(xiàn)切面的場(chǎng)景更多一些。

自定義注解AspectAnn

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface AspectAnn {

}

關(guān)鍵的切面處理類 AspectUtil

@Aspect

public class AspectUtil {

@Pointcut

("execution(* com.game.xiangxuemytest.aspectj.AspectJActivity.aspectTest(..))")

public void pointActionMethod() {}

@Before("pointActionMethod()")

public void testBefore(){

Log.i("AspectJActivity","AspectUtil method1 Before");

}

// @Pointcut

// ("@annotation(com.game.xiangxuemytest.aspectj.AspectAnn)")

// public void pointActionMethod2(AspectAnn ann) {

//

// }

@Pointcut

("execution(@com.game.xiangxuemytest.aspectj.AspectAnn * *(..))")

public void pointActionMethod2() {

}

@After("pointActionMethod2()")

public void testAfter(JoinPoint point) {

Log.i("AspectJActivity", "AspectUtil method2 After");

}

}

@Aspect 標(biāo)志切面的處理類

@Pointcut標(biāo)志切點(diǎn)是誰(shuí),后面跟符合切點(diǎn)的規(guī)則。

1> 包名+類名+方法名來(lái)確定切點(diǎn)規(guī)則:

pointActionMethod()上,com.game.xiangxuemytest.aspectj.AspectJActivity.aspectTest(..)。其中第一個(gè) * 號(hào)表示返回值可為任意類型,括號(hào)內(nèi)表示參數(shù)列表, .. 表示匹配任意個(gè)參數(shù),參數(shù)類型為任何類型

2>以注解來(lái)確定切點(diǎn)規(guī)則的:

方法 pointActionMethod2(),@com.game.xiangxuemytest.aspectj.AspectAnn * (..)),注意兩個(gè) 之間有個(gè)空格,和方式1略有不同。

@Before

切入代碼運(yùn)行在目標(biāo)代碼前,同理還有 @After,@Around等,表示目標(biāo)后,及目標(biāo)前+后。其目的表示切入點(diǎn)運(yùn)行的代碼。同時(shí),由于可以存在多個(gè)切入點(diǎn),所以該注解后要跟上切入點(diǎn)的方法名,

execution,這個(gè)我理解的為實(shí)現(xiàn)切入的方式吧。另外還有一個(gè)call,隨后我們可以根據(jù).class文件看一下兩者的區(qū)別。

運(yùn)行結(jié)果:

AspectUtil method1 Before

aspect test

aspect by annoation test

AspectUtil method2 After

四、實(shí)現(xiàn)原理

通過(guò)Gradle Transform,在class文件生成后至dex文件生成前,遍歷并匹配所有符合AspectJ文件中聲明的切點(diǎn),更改我們?cè)械?class文件,將事先聲明好的代碼在切點(diǎn)前后織入。因此,這個(gè)增加我們的編譯時(shí)間,下面來(lái)看一下上述代碼的最終的.class文件

image.png

為了方便后面的問(wèn)題,我們以截圖的方式顯示,注意紅框部分。從.class文件可以看到,我們?cè)械姆椒ㄇ盎蚝?#xff0c;增加了新的代碼。從而實(shí)現(xiàn)了我們想要的切面功能。

五、call與execution

上面我們說(shuō)了,這兩個(gè)會(huì)影響切面實(shí)現(xiàn)的方式,我們把execution改為call后,看一下其.class

image.png

比較兩者,可以發(fā)現(xiàn),call的方式,不會(huì)改變?cè)械拇a,而是在目標(biāo)方法的調(diào)用前后,進(jìn)行了相應(yīng)的新代碼的插入。

以上是個(gè)人對(duì)AspecJ的一些入門理解,希望能對(duì)小伙伴們有所幫助。

總結(jié)

以上是生活随笔為你收集整理的android aspectj 参数,AspectJ在Android中的使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。