JDK动态代理<一>

2018-04-21  本文已影响8人  吃橘子的冬天

我写技术博客,有一个前提假设:阅读该博客的人都是对此技术点感兴趣但一无所知,而不是已经了然于胸或者能自行理解其要义。因为后者没必要读,前者才可能受益。

也因此,我不赞同写技术文章,一上来就鼓吹技术的强大特性和厉害之处。导致人还没学,就预设了一个高度,尤其是新手读者,很容易因此产生一种仰视的心态。这样的仰视有两点坏处。

第一,仰视带来的盲区影响我们对技术的理解。因为我们倾向于观察它的高明之处,那么就会假设它处处都高明,行行是经典,此时一旦遇到不高明的地方就很容易无法理解,因为我们是按着高明的方向理解的,这就是盲区所在。

第二,仰视背后的心态使我们无法以一颗平常心学习它。当我们一心想要学习一个东西的时候,如果不知道这个东西的难度,那么我们在遇到困难的时候一般都会试图寻找出路,求得解决办法。而如果这个时候有人告诉你,哎呀,这个东西啊,难~。听了之后我们是不是很容易给自己找借口:怪不得我无法理解,原来是因为它难啊,那,就先放放吧。

其实,动态代理和IO、集合类一样,都是普通的平凡的受制于Java的老老实实的几行代码而已,没什么了不起的,他所做的事情,也是我们需要它那样做,它才一步一步那样做的,所以并不会出现凭空就可以代理一个类的情况出现哦。

首先,我们先从代码开始说起。

public class DynmamicProxyHandler implements InvocationHandler {
    //目标对象的引用
    Object target;
    //绑定目标对象,生成代理对象
    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),this);//this 指代当前对象
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("I am dynamic proxy of User || action ...");
        Object object = method.invoke(target,args);
        System.out.println("I am dynamic proxy of User || exit ...");
        return object;
    }
    public static void main(String[] args) throws IOException {
        //创建代理处理对象
        DynmamicProxyHandler proxyHandler = new DynmamicProxyHandler();
        //创建目标对象
        User user = new User();
        //通过绑定目标对象,生成代理对象proxy
        IUser proxy = (IUser) proxyHandler.bind(user);//com.sun.proxy.$Proxy0
        proxy.work();
    }
}

首先,我们要明确一个概念——既然是代理,那么必须持有目标对象才可以对其代理。

那么紧接着问题就来了,如何持有目标对象呢?其实无非就是通过构造器传入,或是通过方法传入。

然后看代码,有一个bind()方法,果然通过此方法传入目标对象,注入到target对象中。

在这里先提个醒,因为这是最容易让人误解的地方。因为我们看到了这个target对象在这个DynamicProxyHandler类中赋的值,也就是说这个DynamicProxyHandler持有了目标对象,于是乎我们本能的认为这个DynamicProxyHandler就是target的代理类。

错!

如果你接受了上面那个想法,那后面的无论怎么看都无法理解。所以先要破了这个看法。DynamicProxyHandler不是代理类,它只是一个代理管理者,这个target在DynamicProxyHandler类中赋值,只是因为下面那个invoke方法有用到。

因此才有下面那句:Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this)

这儿才是生成了一个真正的代理对象。

嘿,它是怎么生成的代理对象呢?
预知后事如何,我们下期再会。

上一篇下一篇

猜你喜欢

热点阅读