Android切面(AOP)的使用 二


大纲如下:


    AOP 是什么?

    AOP 是一种技术,只存在web服务端么?

    AOP 与OOP 的关系以及存在价值?

    AOP和代理的关系,同时代理都有哪些形式?

    代理形式的对比

    Aspectj是什么

    Aspectj的优点 缺点

     Aspectj 语法详解以及使用


上一章节我们提到了 《代理形式的对比》的对比里面静态代理的用法和优劣

这里我们承接上一章的内容继续《代理形式的对比》


代理形式的对比

还记得上一章我们说过的,代理分为动和静,静态已经说完了,我们这里直接说动态的形式。

动态代理:典型实现就是jdk动态代理,通过Proxy(java.lang.reflect.Proxy)对象以及InvocationHandler(java.lang.reflect.InvocationHandler)的具体实现来动态创建代理对象。

客户端(Admin对象)的动态调用形式如下:

public class Admin {

    public void dynamicProxy() {

        IService realService = new ServiceImpl();

        InvocHandlerImpl handler = new InvocHandlerImpl(realService);

        IService proxyService =                 (IService)Proxy.newProxyInstance(handler.getClass().getClassLoader(),

                realService.getClass().getInterfaces(), handler);

        proxyService.queryUserInfo();

        }

        public static void main(String[] args) {

                Admin admin = new Admin();

                admin.dynamicProxy(); //admin.proxyQuery();

        }

}


我们的InvocationHandler对象如下:

public class InvocHandlerImpl implements InvocationHandler{

    Object target;

   public InvocHandlerImpl(Object target){

        this.target = target;

    }

    public Object invoke(Object proxy, Method method, Object[] args)

        throws Throwable {

        System.out.println("------------动态调用前");

        Object object = method.invoke(target, args);

        System.out.println("------------动态调用后");

        return object;

    }

}


我们来说明一下,Proxy.newProxyInstance 这个动作就是在jdk在帮助我们编写上一章里面说的静态代理的那个代理对象,这一点一定要明确。之后我们详细解释一下newProxyInstance这个函数里面的三个参数。

Object newProxyInstance(ClassLoader loader,  Class<?>[] interfaces,InvocationHandler h)

这个函数位于java.lang.reflect.Proxy文件里面,是一个静态函数。

第一个参数classloader:目标对象(被代理对象)的类加载器

第二参数interfaces: 目标对象实现的所有接口类(  请谨记是所有接口,接口 接口 接口)具体的实现动作在 ProxyGenerator.generateProxyClass函数里面(字节码的生成可以自己去了解)

第三个参数 handler:英语直译过来就是"乞求的处理者",这个很拗口(原谅我英语渣),其实我认为它是绑定生成的代理对象和目标对象之前的绑定者,我们稍后看newProxyInstance的具体实现

源代码如下:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException {

        Objects.requireNonNull(h);

        final Class<?>[] intfs = interfaces.clone();

        final SecurityManager sm = System.getSecurityManager();

        if (sm != null) {

            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);

        }

        //下面这一行很重要

        Class<?> cl = getProxyClass0(loader, intfs);

        XXXXXX

}

上面代码斜体我已经标记出来,getProxyClass0(loader, intfs);通过传递的loader和接口去查找生成代理class(在缓存中不存在就会调用生成class逻辑) 这里有一点疑惑,class的生成????我们详细去看一下。

private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) {

 return proxyClassCache.get(loader, interfaces);

}

注意这个proxyClassCache对象是一个WeakCache对象(WeakCache里面的值对象是new ProxyClassFactory()),我们直接去这个WeakCache里面get函数去看,在get函数内部调用了

// lazily construct a Factory

if (factory == null) {

    factory = new Factory(key, parameter, subKey, valuesMap);

}

而这个Factory对象我们在去看里面有一个get()函数

// create new value

V value = null;

try {

    value = Objects.requireNonNull(valueFactory.apply(key, parameter));

} finally{

if (value == null) {

    // remove us on failure values

    Map.remove(subKey, this);

}

}


还记得WeakCache对象的值保存的是什么吗??(new ProxyClassFactory()) 在看上面一段斜体代码

valueFactory.apply(key, parameter) 就是我们这个真正调用Factory apply动作的地方,那么在这个 

apply的函数里面我们可以找到下面这段代码:

byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags);

try {

return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length);

}

好了这样我们就生成了class对象了。。。一切问题迎刃而解!!!!



经过以上的步骤我们确实也生成了代理对象,但是这个过程我们看到它只能对接口进行生成,尴尬了,对普通的类是没办法操作的(多实现单继承决定了这一点)。。。。这种设计虽然有缺憾但是必须得承认确实也很伟大(我们不能因为地心说是错误的就否定米利都学派对于整个人类的贡献),正所谓瑕不掩瑜

这个时候我们需要回顾对比一下上一章的静态代理,静态代理可以对类进行,问题是类文件多,接口修改的话维护代价比较大,动态代理解决生成代理类的问题,也解决了维护的代价,但是自身也有局限性,只能对接口进行实现代理,那么有没有更好的方式方法呢??

答案是肯定的,下一章节我们继续动态代理------编译期生成代理cglib和aspectj

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,192评论 6 511
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,858评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,517评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,148评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,162评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,905评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,537评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,439评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,956评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,083评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,218评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,899评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,565评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,093评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,201评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,539评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,215评论 2 358

推荐阅读更多精彩内容