美文网首页程序员
前端 后端 移动端AOP的实现

前端 后端 移动端AOP的实现

作者: _铁马冰河_ | 来源:发表于2021-02-02 14:21 被阅读0次

    AOP概念

    • 一种程序设计范式
    • 不是OOP的替代品,只是对OOP的一种补充
    • 从主业务中脱离出来横向切面关注点,降低与业务耦合

    前端实现(js)

    由于语言特性,JavaScript本身就具有运行时动态插入逻辑的特性。函数可以接受一切形式函数,保存函数在利用call或者apply,即操作原型就可以。利用 Function.prototype 实现,具体代码如下:

    <script type="text/javascript">
            var viewWillAppear = function () {
                console.log("页面即将展示");
            }
    
            Function.prototype.before = function (fn) {
                var self = this;
                return function(){
                    fn.apply(self,arguments);
                    return self.apply(this,arguments);
                }
            }
    
            Function.prototype.after = function (fn) {
                var self = this;
                return function(){
                    var result = self.apply(this, arguments);
                    fn.apply(this,arguments)
                    return result;
                }
            }
    
         var viewWillAppear = viewWillAppear.before(function () {
                console.log("页面展示之前")
            }).after(function(){
                console.log("页面展示之后")
            })
        </script>
         
         //使用
         <input type="button" onclick="viewWillAppear()" value="展示页面">
    

    在不改动原有业务代码的情况下,继续调用viewWillAppear函数。但是调用前后已经插入业务之外的代码了。

    后端实现(java without spring)

    模拟原有业务代码

    DoAction doAction = new DoActionImpl();
    
    AOPHandler aopHandler = new AOPHandler(doAction);
    
    doAction.viewWillAppear();
    

    使用代理模式实现AOP,新建AOPHandler类并实现InvocationHandler接口

    public class AOPHandler implements InvocationHandler {
    
        private Object object;
    
        public AOPHandler(Object object) {
            this.object = object;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
            System.out.println("viewWillAppear执行前");
    
            Object ret = method.invoke(object,args);
    
            System.out.println("viewWillAppear执行后");
            return null;
        }
    }
    

    实现代理类之后只需在原有调用方法加入代理类如下:

    DoAction doAction = new DoActionImpl();
    AOPHandler aopHandler = new AOPHandler(doAction);
    doAction = (DoAction)
     Proxy.newProxyInstance(DoActionImpl.class.getClassLoader(),
                            new Class[] { DoAction.class },
                            aopHandler);
    
    doAction.viewWillAppear();
    

    即在原有执行代码前后加入了业务代码

    移动端实现 (iOS)

    利用runtime 交换系统与自己定义方法的IMP,代码如下

    SEL systemSel = @selector(viewWillAppear:);
    SEL swizzSel = @selector(swiz_viewWillAppear:);
    Method systemMethod = class_getInstanceMethod([self class], systemSel);
    Method swizzMethod = class_getInstanceMethod([self class], swizzSel);
    
    
    - (void)swiz_viewWillAppear:(BOOL)animated{
        //IMP已经被替换了
        NSLog(@"++viewwillappear之前")
        [self swiz_viewWillAppear:animated];
        NSLog(@"++viewwillappear之后")
    }
    
    
    
    

    不改变原有业务代码的情况下,系统调用viewwillappear的时候,已经加入业务之外的代码了。

    总结

    • 隔离业务之外的代码,降低耦合
    • hook原有方法,侵入性小。C函数的hook可以使用fishhook
    • 减少开发量,方便复用
    • 代码不集中,可能会散落在项目各个位置

    相关文章

      网友评论

        本文标题:前端 后端 移动端AOP的实现

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