jdk动态代理(转)
一旦这样绑定后,那么在进入代理对象方法调用的时候就会到HelloServiceProxy的invoke方法上,invoke方法有三个参数:第一个proxy是代理对象,第二个是当前调用那个方法,第三个是方法的参数。
2、JDK动态代理
这个动态代理还是不好理解的,我们先用一张图来表达它:
好,它的意义是在我们访问一个对象的时候,动态代理可以给我们生成一个代理对象【占位】,它的作用是可以控制【真实对象】的访问。
比方说,你是未成年人,我可能是是去访问你父母,由你父母来代替你访问你,那么你父母就是这个占位,而你就是真实对象。
在JDK动态代理的要求是对象存在接口,所以真正的服务对象必须存在接口。
假设我们现在有这样的一个服务,我给名字它会说: “hello ”+名字。
那么我们先看看这个接口:
- public interface HelloService {
- public void sayHello(String name);
- }
非常简单的接口,然后我们给出实现类:
- public class HelloServiceImpl implements HelloService{
- @Override
- public void sayHello(String name) {
- System.err.println("hello " + name);
- }
- }
好,它实现了这个接口,并且实现了接口的方法。
现在我们要变变,我希望
在说:hello+name前打印:我准备说hello。
之后打印:我说过hello了
如果采用我们的代理对象【占位】显然实现起来非常容易,于是我们首先来生成这个【占位】
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
- public class HelloServiceProxy implements InvocationHandler {
- private Object target;
- /**
- * 绑定委托对象并返回一个【代理占位】
- * @param target 真实对象
- * @return 代理对象【占位】
- */
- public Object bind(Object target, Class[] interfaces) {
- this.target = target;
- //取得代理对象
- <span style="color:#FF0000;"> return Proxy.newProxyInstance(target.getClass().getClassLoader(),
- target.getClass().getInterfaces(), this); </span>
- }
- @Override
- /**
- * 同过代理对象调用方法首先进入这个方法.
- * @param proxy --代理对象
- * @param method -- 方法,被调用方法.
- * @param args -- 方法的参数
- */
- public Object invoke(Object proxy , Method method, Object[] args) throws Throwable {
- System.err.println("############我是JDK动态代理################");
- Object result = null;
- //反射方法前调用
- System.err.println("我准备说hello。");
- //反射执行方法 相当于调用target.sayHelllo;
- result=method.invoke(target, args);
- //反射方法后调用.
- System.err.println("我说过hello了");
- return result;
- }
- }
这里的bind方法里面有句:
- Proxy.newProxyInstance(target.getClass().getClassLoader(),
- target.getClass().getInterfaces(), this);
它的意义就是生成一个代理对象,这里有三个参数:第一个参数是类加载器,第二个参数是或者对象的接口(代理对象挂在那个接口下),第三个参数this代表当前HelloServiceProxy类,换句话说是使用HelloServiceProxy作为对象的代理。
一旦这样绑定后,那么在进入代理对象方法调用的时候就会到HelloServiceProxy的invoke方法上,invoke方法有三个参数:第一个proxy是代理对象,第二个是当前调用那个方法,第三个是方法的参数。
比方说,现在HelloServiceImpl对象(obj)用bind方法绑定后,返回其【占位】(proxy),我们在调用proxy.sa6yHello("张三"),那么它就会进入到HelloServiceProxy的invoke()方法。而invoke参数中第一个便是代理对象proxy,方法便是sayHello,参数是"张三"。那么我们就可以通过反射技术调度真实对象的方法。
现在让我们看看测试代码:
- public class ProxyTest {
- public static void main(String[] args) {
- HelloServiceProxy proxy = new HelloServiceProxy();
- HelloService service = new HelloServiceImpl();
- //绑定代理对象。
- service = (HelloService) proxy.bind(service, new Class[] {HelloService.class});
- //这里service经过绑定,就会进入invoke方法里面了。
- service.sayHello("张三");
- }
- }
好,我们运行一下,看一下结果。
- ############我是JDK动态代理################
- 我准备说hello。
- hello 张三
- 我说过hello了
好了,我们这样就可以看到动态代理。
正确的理解反射和动态代理是我们进行MyBATIS底层的基础,尤其是动态代理,如果还不了解务必要多做上面的例子,切实理解好。
本文转自:http://blog.csdn.net/ykzhen2015/article/details/50312651
最新文章
- [转载]LazyWriter(惰性写入器) 进程的作用
- python模块之configparser
- php部分--session的三种用法
- storm - 基础概念整理
- javascript 键值对
- android Intent.createChooser 应用选择
- 广播,多播,IGMP:网际组管理协议
- 物料事务处理接口表 MTL_TRANSACTIONS_INTERFACE 账户别名使用 及 提示无效的分配账户字段
- POJ	3548 Restoring the digits
- C++ 拷贝构造函数、拷贝赋值运算符、析构函数
- poj2337欧拉回路要求输出路径
- Vue(小案例_vue+axios仿手机app)_图片列表操作
- dubbo和zikkeper的使用
- Django 内的母版-子html规则
- 016.OpenStack及云计算(面试)常见问题
- spring3-mvc-maven-hello-world-master mvn jetty:run 及 mvn war:war 指令
- 下载Chrome独立版(alternate/offline Installer)的地方
- mysql格式化日期的函数
- 一台 linux 主机装两个mysql
- jquery特效:无缝向上循环滚动列表