美文网首页
AOP切面编程

AOP切面编程

作者: 贾里 | 来源:发表于2019-02-17 12:53 被阅读8次

    AOP切面编程

    image.png

    1.什么是AOP

    就是吧我们某个方法的功能提出来与一批对象进行隔离,这样与一批对象之间降低耦合性,就可以对某个功能进行编程;

    OOP:面对对象编程

    Android面向对象的七大服务:


    image.png

    AOP:面向切面编程

    假如在上面的七大服务中,添加一个日志服务,如果面向对象的思维,日志模块需要暴露一个调用接口,每个模块去调用日志模块方法,这样产生的问题:

    • 每个模块都含有日志模块的方法,产生了耦合,违背了模块单一原则;
    • 日志模块改动会导致其他模块也都需要改动,牵一发动全身;

    2.AOP的意义:解耦合

    把某个功能统一集中起来,集中处理,跨模块进行编程;
    例子:
    每一个模块都有自己的功能,比如图书浏览、商品模块、数据库模块,现在每一个模块度要进行一个权限检查,如果使用普通的面向对象来进行权限检查(判断用户角色),就会产生以下问题:

    • 1.权限检查的规则一旦改了,每个模块都要改动;
    • 2.各个模块之间产生了耦合,违反单一原则;

    如何解决:采用面向切片的方式

    image.png

    3.AOP的应用

    • 日志
    • 用户行为统计
    • 权限管理

    4.AOP实践

    AndroidStudio中Gradle的配置:参考

    import org.aspectj.bridge.IMessage
    import org.aspectj.bridge.MessageHandler
    import org.aspectj.tools.ajc.Main
    buildscript {
        repositories {
            mavenCentral()
        }
        dependencies {
            classpath 'org.aspectj:aspectjtools:1.8.9'
            classpath 'org.aspectj:aspectjweaver:1.8.9'
        }
    }
    
    apply plugin: 'com.android.application'
    
    repositories {
        mavenCentral()
    }
    
    android {
        compileSdkVersion 23
        buildToolsVersion '23.0.1'
        defaultConfig {
            applicationId "com.example.administrator.dn_02_aop"
            minSdkVersion 15
            targetSdkVersion 23
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }
    
    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;
                }
            }
        }
    }
    
    
    
    dependencies {
        compile fileTree(include: ['*.jar'], dir: 'libs')
        androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
            exclude group: 'com.android.support', module: 'support-annotations'
        })
        compile 'com.android.support:appcompat-v7:23.0.0'
        testCompile 'junit:junit:4.12'
        compile files('libs/aspectjrt.jar')
    }
    

    4.1例子:

    image.png
    原始方法(面向对象思想):
    public class MainActivity extends AppCompatActivity {
        private static final String TAG = "dongnao";
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        /**
         * 摇一摇的模块
         *
         * @param view
         */
        public  void mShake(View view)
        {
                SystemClock.sleep(3000);
                Log.i(TAG,"  摇到一个嫩模:  约不约");
        }
    
    
        /**
         * 语音的模块
         *
         * @param view
         */
        public  void mAudio(View view)
        {
            long beagin=System.currentTimeMillis();
    
            //摇一摇的代码逻辑
            {
                SystemClock.sleep(3000);
    
                Log.i(TAG,"  美女  睡不着   热不热");
    
            }
    
            Log.i(TAG,"消耗时间:  "+(System.currentTimeMillis()-beagin)+"ms");
        }
    
        /**
         * 摇一摇的模块
         *
         * @param view
         */
        public  void mText(View view)
        {
            //统计用户行为 的逻辑
            Log.i(TAG,"文字:  使用时间:   "+simpleDateFormat.format(new Date()));
            long beagin=System.currentTimeMillis();
    
            //摇一摇的代码逻辑
            {
                SystemClock.sleep(3000);
                Log.i(TAG,"  热   我们去18");
    
            }
    
            Log.i(TAG,"消耗时间:  "+(System.currentTimeMillis()-beagin)+"ms");
        }
    
    }
    
    面向切面:

    定义切点:

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface BehaviorTrace {
        String value();
        int type();
    }
    

    切面:

    /**
     * 切面
     * 你想要切下来的蛋糕
     */
    @Aspect
    public class BehaviorAspect {
        private static final String TAG = "dongnao";
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        /**
         * 如何切蛋糕,切成什么样的形状
         * 切点
         */
        @Pointcut("execution(@com.example.administrator.dn_02_aop.BehaviorTrace  * *(..))")
        public void annoBehavior()
        {
    
        }
    
        /**
         * 切面
         * 蛋糕按照切点切下来之后   怎么吃
         * @param point
         * @return
         * @throws Throwable
         */
        @Around("annoBehavior()")
        public Object dealPoint(ProceedingJoinPoint point) throws  Throwable
        {
            //方法执行前
            MethodSignature methodSignature= (MethodSignature) point.getSignature();
            BehaviorTrace  behaviorTrace=methodSignature.getMethod().getAnnotation(BehaviorTrace.class);
            String contentType=behaviorTrace.value();
            int type=behaviorTrace.type();
            Log.i(TAG,contentType+"使用时间:   "+simpleDateFormat.format(new Date()));
            long beagin=System.currentTimeMillis();
            //方法执行时
            Object object=null;
            try {
                 object=point.proceed();
            }catch (Exception e)
            {
    
            }
    
    
            //方法执行完成
            Log.i(TAG,"消耗时间:  "+(System.currentTimeMillis()-beagin)+"ms");
    
            return  object;
        }
    
    
    }
    

    业务:

       @BehaviorTrace(value = "摇一摇",type = 1)
        public  void mShake(View view)
        {
                SystemClock.sleep(3000);
                Log.i(TAG,"  摇到一个嫩模:  约不约");
        }
    

    相关文章

      网友评论

          本文标题:AOP切面编程

          本文链接:https://www.haomeiwen.com/subject/eeqnxftx.html