我写技术博客,有一个前提假设:阅读该博客的人都是对此技术点感兴趣但一无所知,而不是已经了然于胸或者能自行理解其要义。因为后者没必要读,前者才可能受益。
也因此,我不赞同写技术文章,一上来就鼓吹技术的强大特性和厉害之处。导致人还没学,就预设了一个高度,尤其是新手读者,很容易因此产生一种仰视的心态。这样的仰视有两点坏处。
第一,仰视带来的盲区影响我们对技术的理解。因为我们倾向于观察它的高明之处,那么就会假设它处处都高明,行行是经典,此时一旦遇到不高明的地方就很容易无法理解,因为我们是按着高明的方向理解的,这就是盲区所在。
第二,仰视背后的心态使我们无法以一颗平常心学习它。当我们一心想要学习一个东西的时候,如果不知道这个东西的难度,那么我们在遇到困难的时候一般都会试图寻找出路,求得解决办法。而如果这个时候有人告诉你,哎呀,这个东西啊,难~。听了之后我们是不是很容易给自己找借口:怪不得我无法理解,原来是因为它难啊,那,就先放放吧。
其实,动态代理和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)
这儿才是生成了一个真正的代理对象。
嘿,它是怎么生成的代理对象呢?
预知后事如何,我们下期再会。