当前位置: 首页 > 科技观察

浅谈AndroidAOP三剑客AndroidAPT技术

时间:2023-03-19 12:43:38 科技观察

AndroidAOP三剑客:APT、AspectJ、JavassistAndroidAPTAPT(AnnotationProcessingTool的缩写),代码编译时可以解析Annotations,生成新的Java文件减少手动代码输入。现在很多主流库都使用APT,比如Dagger2、ButterKnife、EventBus3等代表性框架:DataBindingDagger2ButterKnifeEventBus3DBFlowAndroidAnnotation使用姿势1、在android项目中,创建一个javaModule,写一个类继承AbstractProcessor@AutoService(Processor.class)//javax.annotation.processing.IProcessor@SupportedSourceVersion(SourceVersion.RELEASE_7)//java@SupportedAnnotationTypes({//注解处理器支持的注解类型"com.annotation.SingleDelegate","com.annotation.MultiDelegate"})publicclassAnnotationProcessorextendsAbstractProcessor{publicstaticfinalStringPACKAGE="com.poet.delegate";publicstaticfinalStringCLASS_DESC="Frompoetcompiler";publicFilerfiler;//文件相关辅助类publicElementselements;//元素相关辅助类publicMessagermessager;//类型相关辅助类;@Overridepublicbooleanprocess(Setset,RoundEnvironmentroundEnvironment){filer=processingEnv.getFiler();elements=processingEnv.getElementUtils();messager=processingEnv.getMessager();types=进程ingEnv.getTypeUtils();newSingleDelegateProcessor().process(set,roundEnvironment,this);newMultiDelegateProcessor().process(set,roundEnvironment,this);returntrue;}}2、在继承AbstractProcessor类中的process方法,处理我们的自己定义的注解,生成代码:publicclassSingleDelegateProcessorimplementsIProcessor{@Overridepublicvoidprocess(Setset,RoundEnvironmentroundEnv,AnnotationProcessorabstractProcessor){//查询注解是否存在.typesIn(elementSet);if(typeElementSet==null||typeElementSet.isEmpty()){return;}//循环处理注解for(TypeElementtypeElement:typeElementSet){if(!(typeElement.getKind()==ElementKind.INTERFACE)){//只处理接口类型continue;}//处理SingleDelegate,只处理annotation.classNameImpl()不为空SingleDelegateannotation=typeElement.getAnnotation(SingleDelegate.class);if("".equals(annotation.classNameImpl())){continue;}Delegateddelegate=annotation.delegate();//添加构造函数MethodSpec.BuilderconstructorBuilder=MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC);//创建类名相关classbuilderTypeSpec.Builderbuilder=ProcessUtils.createTypeSpecBuilder(typeElement,annotation.classNameImpl());//Processdelegatebuilder=ProcessUtils.processDelegate(typeElement,builder,constructorBuilder,delegate);//检查是否继承其他接口builder=processSuperSingleDelegate(abstractProcessor,builder,constructorBuilder,typeElement);//完成构造函数.build());//创建JavaFileJavaFilejavaFile=JavaFile.builder(AnnotationProcessor.PACKAGE,builder.build()).build();try{javaFile.writeTo(abstractProcessor.filer);}catch(IOExceptione){e.printStackTrace();}}}3、在项目中添加annotationProcessor项目Gradle引用compileproject(':apt-delegate-annotation')annotationProcessorproject(':apt-delegate-compiler')4、如果有自定义注解,则创建java魔都le,特意放入自定义注解项目和aptModule都需要引用自定义注解Module4-1,主项目:compileproject(':apt-delegate-annotation')annotationProcessorproject(':apt-delegate-compiler')4-2,aptModule:compileproject(':apt-delegate-annotation')compile'c??om.google.auto.service:auto-service:1.0-rc2'compile'c??om.squareup:javapoet:1.4.0'5,生成的源码在build/generated/source/可以看到apt下的难点。对于apt本身来说,完全没有困难可言。一是难点在于设计模式和解耦思想的灵活运用,二是繁琐的代码生成。可以手动拼接字符串,当然还有更高级的。玩法使用squareup的javapoet通过构建器模式构建您想要的任何源代码。它的优点不用多说,看代表框架的源码就可以学到很多新姿势。一句话:它可以做任何你不想做的复杂工作,它可以帮你写任何你不想重复的代码。懒人福利,老司机必备技能,可以提高车速,让你以任何姿势漂移。它可以生成任何源代码供你在任何地方使用,就像剑客的宝剑,快如风,无所不能我想研究一下,APT还能用在什么地方,比如:Repository层?APT在Repository层在尝试理解APT和简单学习后,在构建Repository层时,发现有一些简单的代码重复模板。每次增加一个新的接口,很多地方都需要简单的修改。能不能自动生成一些代码,减少修改次数?Repository层IRemoteDataSource、RemoteDataSourceImpl远程数据源,属于网络请求相关的ILocalDataSource、LocalDataSourceImpl本地数据源,属于本地数据持久化相关的IRepository、RepositoryImpl仓库代理类,代理远程数据源和本地数据源Repository层APT设计思想见具体实现大多数类都是以代理类的形式调用的:在方法中调用代理对象,方法名和参数、返回值类型相同。显然,APT可以在简单的情况下尝试,具体实现类中只有一个代理对象。复杂情况下,有多个代理对象,方法上有一些变化预期结果:自动生成RemoteDataSourceImpl自动生成LocalDataSourceImpl自动生成RepositoryImpl自动生成RepositoryImpl注解设计定义要实现类的自动生成,首先要知道需要什么:方便自动生成java文件的类库,可以使用squareupjavapoet通过自定义注解配置参数自动生成需要组成的类名、代理对象、方法集,获取Delegate@Retention(RetentionPolicy.SOURCE)@Target(ElementType.TYPE)public@interfaceDelegate{/*在AbstractProcessor**delegateclasspackage*/StringdelegatePackage();/***delegateclassname*/StringdelegateClassName();/***delegatesimplename*/StringdelegateSimpleName();}SingleDelegate@Retention(RetentionPolicy.SOURCE)@Target(ElementType.TYPE)public@interfaceSingleDelegate{/***implclassname*/StringclassNameImpl();/***delegatedata*/Delegatedelegate();}MultiDelegate@Retention(RetentionPolicy.SOURCE)@Target(ElementType.TYPE)public@interfaceMultiDelegate{/***implclassname*/StringclassNameImpl();/***delegatelist*/Delegate[]Delegates();}处理自定义注解,生成代码注解motionProcessor@AutoService(Processor.class)//javax.annotation.processing.IProcessor@SupportedSourceVersion(SourceVersion.RELEASE_7)//java@SupportedAnnotationTypes({//注解处理器支持的注解类型"com.annotation.SingleDelegate","com.annotation.MultiDelegate"})publicclassAnnotationProcessorextendsAbstractProcessor{publicstaticfinalStringPACKAGE="com.poet.delegate";publicstaticfinalStringCLASS_DESC="Frompoetcompiler";publicFilerfiler;//文件相关辅助类publicElementselements;//元素相关辅助类publicElementselements;//辅助类相关元素publicMessagermess/辅助类publicTypes类型;@Overridepublicbooleanprocess(Setset,RoundEnvironmentroundEnvironment){filer=processingEnv.getFiler();elements=processingEnv.getElementUtils();messager=processingEnv.getMessager();types=processingEnv。getMessager();types=processingEnv.getFiler();types=processingEnv.getMessager();types=processingEnv.getFiler();newSingleDelegateProcessor().process(set,roundEnvironment,this);newMultiDelegateProcessor().process(set,roundEnvironment,this);returntrue;}}