android 中AsepectJ 使用

   源码地址: https://download.csdn.net/download/dreams_deng/12239703   

1.Aop实现方式: 动态代理、AspetJ

   1. 加载期间    类加载   动态代理
   2. 编译时  apt、操作字节码
        javac         aspecj(编辑器)修改.class
   java -----> .class ---------------------> .class修改注入

    aspectJ 在 Javac编译 以后 读取 .class 文件 使用apectJ 进行 替换

1.1. 静态代理案例:

 静态代理:
    被代理类和代理类同时实现相应的一套接口

 动态代理:
   在程序运行时候动态的创建代理类,
     我要买房子...买手机...  动态创建买房子、买手机代理类....

package com.atguigu.java1;
//静态代理模式
//接口
interface ClothFactory{
	void productCloth();
}
//被代理类
class NikeClothFactory implements ClothFactory{

	@Override
	public void productCloth() {
		System.out.println("Nike工厂生产一批衣服");
	}	
}
//代理类
class ProxyFactory implements ClothFactory{
	ClothFactory cf;
	//创建代理类的对象时,实际传入一个被代理类的对象
	public ProxyFactory(ClothFactory cf){
		this.cf = cf;
	}
	
	@Override
	public void productCloth() {
		System.out.println("代理类开始执行,收代理费$1000");
		cf.productCloth();
	}
	
}

public class TestClothProduct {
	public static void main(String[] args) {
		NikeClothFactory nike = new NikeClothFactory();//创建被代理类的对象
		ProxyFactory proxy = new ProxyFactory(nike);//创建代理类的对象
		proxy.productCloth();
	}
}

1.2. 动态代理 :

package com.atguigu.java1;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;





//动态代理的使用,体会反射是动态语言的关键
interface Subject {
	void action();
}

// 被代理类
// 2. 第二部:被代理类实现
class RealSubject implements Subject {
	public void action() {
		System.out.println("我是被代理类,记得要执行我哦!么么~~");
	}
}

class EatSubject implements Subject{

	@Override
	public void action() {
		System.out.println("我要吃饭");
	}
}

class DrinkWaterSubject implements Subject{

	@Override
	public void action() {
		 System.out.println("我要喝水.....我还要喝水.....");
	}
}

 // 1. 第一步, 这是系统封装好的 InvoacationHandler

class MyInvocationHandler implements InvocationHandler {
	Object obj;// 实现了接口的被代理类的对象的声明

	// ①给被代理的对象实例化②返回一个代理类的对象
	public Object blind(Object obj) {
		this.obj = obj;
		// 这里返回一个代理类对象,参数意义
		// 1. obj.getClass().getClassLoader()       表示代理类使用和被代理类同样的类加载器
		// 2. obj.getClass().getInterfaces()        表示返回代理类对象实现了和被代理类对象同样的接口
		return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
				.getClass().getInterfaces(), this);
	}
	//当通过代理类的对象发起对被重写的方法的调用时,都会转换为对如下的invoke方法的调用
	// methond.invoke调用被代理类的方法
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		//method方法的返回值时returnVal
		
		HumanUtils humanUtils=new HumanUtils();
		humanUtils.method1();
		
		Object returnVal = method.invoke(obj, args);
		
		humanUtils.method2();
		
		return returnVal;
	}

}


class HumanUtils{
	public void method1(){
		System.out.println("我是method----1");
	}
	public void method2(){
		System.out.println("我是method----2");
	}
}

public class TestProxy {
	public static void main(String[] args) {
		//1.被代理类的对象
		RealSubject real = new RealSubject();
		//2.创建一个实现了InvacationHandler接口的类的对象
		MyInvocationHandler handler = new MyInvocationHandler();
		//3.调用blind()方法,动态的返回一个同样实现了real所在类实现的接口Subject的代理类的对象。
		Object obj = handler.blind(real);
		Subject sub = (Subject)obj;//此时sub就是代理类的对象
		
		sub.action();//转到对InvacationHandler接口的实现类的invoke()方法的调用
		
		//再举一例
		NikeClothFactory nike = new NikeClothFactory();
		ClothFactory proxyCloth = (ClothFactory)handler.blind(nike);//proxyCloth即为代理类的对象
		proxyCloth.productCloth();
		
		// 3. 具体调用
		EatSubject eatSubject=new EatSubject();
		Subject sub1= (Subject) handler.blind(eatSubject);
		sub1.action();
		
		
		DrinkWaterSubject drinkWater=new DrinkWaterSubject();
		Subject drinksubjectinterface= (Subject) handler.blind(drinkWater);
		drinksubjectinterface.action();
		
		
		
	}
}

 

  2. AspectJ 使用流程: 

 例子:子线程切换

1.  添加依赖

  compile 'com.android.support:design:24.2.1'
    compile 'io.reactivex.rxjava2:rxandroid:2.0.2'

2. 配置aspectJ, 在gradle中 android {} 同级别目录

import org.aspectj.tools.ajc.Main
//配置aspectJ
//  aspectJ 在 Javac编译 以后 读取 .class 文件 使用apectJ 进行 替换
android.applicationVariants.all{
    //编译Java代码的任务
    JavaCompile javaCompile = it.javaCompile
    // javac 执行以后 --doLast
        javaCompile.doLast {
      //  println "在编译之后执行"
        //执行 aspectJ 修改字节码的操作
        String[] args = [
                // 指定jdk
                "-1.8",
                // aspectJ 处理的源文件,aspectJ处理的源文件是.class,这个目录就是Java编译后的app\build\intermediates\classes\debug
                "-inpath",javaCompile.destinationDir.toString(),
                //  aspectJ 处理完成以后输出的目录
                "-d",javaCompile.destinationDir.toString(),
                "-aspectpath",javaCompile.classpath.asPath,
                "-classpath",javaCompile.classpath.asPath,
                "-bootclasspath",project.android.bootClasspath.join(File.pathSeparator)
        ]
        //  调用aspectJ编译器
        new Main().runMain(args,false)
    }
}

3.  自定义注解 @Async 

package com.denganzhi.myappliction;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created by Administrator on 2018\10\12 0012.
 */


// 什么时间去操作注解,注解的生命周期
    // source   源码级别,在编译时候丢弃
    //  RetentionPolicty.class表示该注解在编译编译时期使用,在运行期间丢弃,不能获取
    // RetentionPolicty.RUNTIME 表示该注解在运行期使用,可以通过放射获取
// @target表示该注解使用在方法上
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
// 修饰属性、方法、........
public @interface Async {
}

4.  定义切面

@Pointcut  -->doAsync() 指定切入点

 @Around("doAsync()")  切入点代码对应逻辑

@Aspect
public class AsyncAspect {

    /*  @around:围绕方法执行,就是需要自己调用方法
        @before: 在方法执行之前执行
        @after:  在方法执行之后执行
     *
     */

    @Pointcut("execution(@com.denganzhi.myappliction.Async void *(..))")
    public void doAsync(){

    }

 // RXJava实现切换子线

//    @Around("doAsync()")
//    public void doAsyncMethod(final ProceedingJoinPoint joinPoint){
//        //切换线程
//        Completable.create(new CompletableOnSubscribe() {
//            @Override
//            public void subscribe(CompletableEmitter emitter) throws Exception {
//                //子线程
//                //执行原来的方法
//                try{
//                    joinPoint.proceed();
//                }catch (Throwable throwable){
//                    throwable.printStackTrace();
//                }
//            }
//        }).subscribeOn(Schedulers.io()).subscribe();
//
//    }
    
  // 直接使用AspectJ
    @Around("doAsync()")
    public void doAsyncMethod(final ProceedingJoinPoint joinPoint){
      
        new Thread(){
            @Override
            public void run(){
                try{
                    joinPoint.proceed();
                }catch (Throwable throwable){
                    throwable.printStackTrace();
                }
            }
        }.start();

    }

}

5.  使用注解

public class MainActivity extends Activity {

    Button btn1;



    @MyAnnotation(value = "xiaohei",name = "小明")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn1 = (Button)findViewById(R.id.btn1);


        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                 readFile();
                // 切面的真实应用    
            }
        });
    }


   @Async
    public void readFile(){

       Log.e("denganzhi1","读取文件:"+Thread.currentThread().toString());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        showResult("小明","xiaohei");
    }
}

3.  其他标签使用

@AfterReturning:  在函数返回值以后调用切入点函数
@AfterThrowing: 在函数抛出异常以后调用切入点函数
@Around:  手动调用 函数在切入点

1. 定义注解 @Main 


package com.denganzhi.myappliction;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created by Administrator on 2018\10\12 0012.
 */

@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
public @interface Main {
}

2. 定义切面


@Aspect
public class MainAspect {


    static  Handler mhandler=new Handler(Looper.getMainLooper());


    @Pointcut("execution(@com.denganzhi.myappliction.Main * *(..))")
    public void doMain(){

    }

    // 直接在标签中注解,不使用 @Pointcut
    @AfterThrowing(value = "execution(public int com.denganzhi.myappliction.ShowHello.showMessage(int,int))"
            ,throwing = "ex")
    public void doHelloException(final ProceedingJoinPoint joinPoint, Exception ex){
        Log.e("denganzhi1","异常是---------》"+ex);
    }
    @AfterReturning(value = "execution(public int com.denganzhi.myappliction.ShowHello.showMessage(int,int))"
            ,returning = "result")
    public void doHelloException(final ProceedingJoinPoint joinPoint, Object result){
        Log.e("denganzhi1","返回值是:---------》"+result);
    }

    @Around("execution(public int com.denganzhi.myappliction.ShowHello.showMessage(int,int))")
    public Object doHello(final ProceedingJoinPoint joinPoint){

        Object result=null;
        try {
            // 参数
           // Object[] args= joinPoint.getArgs();
            // 返回值
            String methodName= joinPoint.getSignature().getName();
             result= joinPoint.proceed();

            List<Object> args= Arrays.asList(joinPoint.getArgs());

           // String str= Arrays.toString(args);

            Log.e("denganzhi1","methodName:"+methodName+"  返回值是:"+result+" args:"+args);

        } catch (Throwable throwable) {
            //throwable.printStackTrace();

            Log.e("denganzhi1","异常通知:"+throwable.getMessage());

           // throw new RuntimeException(throwable);
        }
          return  result;
    }




    //RXJava
  /*  @Around("doMain()")
    public void doMainMethod(final ProceedingJoinPoint joinPoint){
        //保证在主线程
        if(Looper.myLooper()==Looper.getMainLooper()){
            try {
                joinPoint.proceed();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
            return;
        }
        //如果不在 切换到主线程
        Completable.create(new CompletableOnSubscribe() {
            @Override
            public void subscribe(CompletableEmitter emitter) throws Exception {
                try{
                    joinPoint.proceed();
                }catch (Throwable throwable){
                    throwable.printStackTrace();
                }
            }
        }).subscribeOn(AndroidSchedulers.mainThread()).subscribe();
    }*/


  /*  @around:围绕方法执行,就是需要自己调用方法
        @before: 在方法执行之前执行
        @after:  在方法执行之后执行
     */

  // 异常通知,在执行方法抛出异常以后
//    @AfterThrowing(value = "execution(@com.denganzhi.myappliction.Main * *(..))",
//            throwing = "ex")
//    public void doMainMethodAfter(final ProceedingJoinPoint joinPoint,final Exception ex){
//    }



//  返回值通知,在执行方法返回值以后,获取方法返回值
//    @AfterReturning(value = "execution(@com.denganzhi.myappliction.Main * *(..))",
//    returning = "result")
//    public void doMainMethodAfter(final ProceedingJoinPoint joinPoint,final Object result){
//    }


    // 指定切入点
   @Around("doMain()")
    public void doMainMethod(final ProceedingJoinPoint joinPoint){
        //保证在主线程
        if(Looper.myLooper()==Looper.getMainLooper()){
            try {
                joinPoint.proceed();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
            return;
        }
       Log.e("denganzhi1","来到这里没有");
       mhandler.post(new Runnable() {
           @Override
           public void run() {
               try {
                   // 参数
                   Object[] args= joinPoint.getArgs();
                   // 返回值
                   Object result= joinPoint.proceed();


                   String str= Arrays.toString(args);

                   Log.e("denganzhi1","参数是:"+str+"返回值是:"+result);

               } catch (Throwable throwable) {
                   throwable.printStackTrace();
               }
           }
       });
    }




}

 3. 使用注解标签


public class MainActivity extends Activity {

    @MyAnnotation(value = "xiaohei",name = "小明")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

  @Main
    public   void  showResult(String arg1,String arg2){
          Log.e("denganzhi1","写入文件:"+Thread.currentThread().toString());
         Toast.makeText(MainActivity.this,"更新UI", Toast.LENGTH_LONG).show();

    }
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值