转自: http://langyu.iteye.com/blog/410071
没事的时候翻看lang.reflect包下的代码,发现有两部分内容:涉及反射和动态代理。
很多地方都可以看到动态代理的影子,只是一直没仔细看下。
在学习之前,先提出几个问题,带着问题来看代码:
1.什么是动态代理?
2.为什么使用动态代理?
3.使用它有哪些好处?
4.哪些地方需要动态代理?
--------------------分隔线-----------------------------
和动态代理有关的有两个类
1.interface InvocationHandler
Object invoke(Object proxy, Method method, Object[] args)
只这一个方法,后面再说
2.class Proxy
真正表示动态代理的类,提供两个静态方法:
Class<?> getProxyClass(ClassLoader loader, Class<?>[] interface)
用来产生代理类,参数要提供interface数组,它会生成这些interface的“虚拟实现”,
用来冒充真实的对象。
Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
产生代理对象,多了InvocationHandler参数(只是InvocationHandler接口的实现类),
它与代理对象关联,当请求分发到代理对象后,会自动执行h.invoke(...)方法,
invoke方法就是我们用来做N多事情的地方 -_-。
--------------------分隔线-----------------------------
看完上面的代码,大致明白动态代理的含义:
A接口有c方法,类B实现A接口,原本应该是执行B类中的c方法,可现在不这样做;
我声明产生B类的代理类B',由它来冒充B类的“兄弟”并“实现”A接口,
对外界来说B'应该也有c方法,可当真正调用它的时候,
它会去执行与它关联InvocationHandler的invoke()方法,
在这个方法里面你可以做很多事情。这样,这个请求就被“代理”到其它地方去了。
下面是根据我的理解画的一个说明图
--------------------分隔线-----------------------------
引用网上的一个例子来说明问题(有部分改动,转载自:http://callan.iteye.com/blog/161806)
真实的接口:
- public interface Hello {
-
void sayHello(String to);
-
void print(String p);
- }
public interface Hello {
void sayHello(String to);
void print(String p);
}
它的真实实现类:
- public class HelloImpl
implements Hello {
-
public void sayHello(String to) {
-
System.out.println("Say hello to " + to);
- }
-
public void print(String s) {
-
System.out.println("print : " + s);
- }
- }
public class HelloImpl implements Hello {
public void sayHello(String to) {
System.out.println("Say hello to " + to);
}
public void print(String s) {
System.out.println("print : " + s);
}
}
在这里生成与代理类相关联的InvocationHandler对象
- public class LogHandler
implements InvocationHandler {
-
private Object dele;
-
public LogHandler(Object obj) {
-
this.dele = obj;
- }
-
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
- doBefore();
-
- Object result = method.invoke(dele, args);
- after();
-
return result;
- }
-
private void doBefore() {
-
System.out.println("before....");
- }
-
private void after() {
-
System.out.println("after....");
- }
- }
public class LogHandler implements InvocationHandler {
private Object dele;
public LogHandler(Object obj) {
this.dele = obj;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
doBefore();
//在这里完全可以把下面这句注释掉,而做一些其它的事情
Object result = method.invoke(dele, args);
after();
return result;
}
private void doBefore() {
System.out.println("before....");
}
private void after() {
System.out.println("after....");
}
}
最后是测试类:
- public class ProxyTest {
-
public static
void main(String[] args) {
-
HelloImpl impl = new HelloImpl();
-
LogHandler handler = new LogHandler(impl);
-
- Hello hello = (Hello) Proxy.newProxyInstance(impl.getClass().getClassLoader(), impl.getClass().getInterfaces(), handler);
-
-
hello.print("All the test");
-
hello.sayHello("Denny");
- }
- }
public class ProxyTest {
public static void main(String[] args) {
HelloImpl impl = new HelloImpl();
LogHandler handler = new LogHandler(impl);
//这里把handler与impl新生成的代理类相关联
Hello hello = (Hello) Proxy.newProxyInstance(impl.getClass().getClassLoader(), impl.getClass().getInterfaces(), handler);
//这里无论访问哪个方法,都是会把请求转发到handler.invoke
hello.print("All the test");
hello.sayHello("Denny");
}
}
这里是输出结果:
- before....
- print : All the test
- after....
- before....
- Say hello to Denny
- after....
before....
print : All the test
after....
before....
Say hello to Denny
after....
--------------------分隔线-----------------------------
最后试着来回答之前提出的问题:
1.什么是动态代理?
一种用于转发请求,进行特殊处理的机制,“动态”应该指的是“运行期”。
2.为什么使用动态代理?
可以对请求进行任何处理(如事务,日志等,这都是网上说的,我当然可以做任何处理)
3.使用它有哪些好处?
如上
4.哪些地方需要动态代理?
不允许直接访问某些类;对访问要做特殊处理等,我只能想到这些。 --------------------分隔线-----------------------------
其它一些想法:
1.如果想声明产生B类的代理类,那个B类必须要实现接口,如果没有接口,
代理类就不能伪装成B类的“兄弟”,也就没有存在的意思,
其实也可以伪装成B类的“孩子”,对外他们有共同的接口,可以这样做吧?
2.当请求代理类的方法时,这个请求会被转到执行与代理类关联InvocationHandler
的invoke方法。那InvocationHandler到底是什么?对它的理解可以是这样:
它用来处理方法的调用,实现类也有同样的意义;与代理类对象相关联则表示,
它就是负责处理代理类应该有的动作,把所有的方法请求分发到invoke这个方法上。
分享到:
相关推荐
java语言反射与动态代理学习笔记
NULL 博文链接:https://whp0731.iteye.com/blog/343787
《java jdk 7学习笔记》适合java的初中级读者,以及广大java应用开发人员。 作译者 林信良(网名:良葛格) 学历:台湾大学电机工程学系 经历:台湾升阳教育训练技术顾问、专业讲师,oracle授权训练中心讲师 ...
16-Java代理模式的学习笔记1
JAVA,设计模式动态代理,学习笔记。
Java基础常识、如何安装Java工具、Java语言的基础组成、Java面向对象、Java多线程、Java常用类、集合(重点)、IO流、GUI图形界面、网络编程、正则表达式、反射、注解、类加载器、动态代理等等,另外还包括银行管理...
动态代理及其生成的代理类,可以反编译查看其类的结构。
内容概要:动态代理学习笔记,适合刚接触maven的人能让你快速入门。 适用人群:大学生或者初接触动态代理的人 使用场景及目标:mybatis框架的前驱知识
Java基础学习(4)——动态代理 《Java多线程核心技术》读书笔记 JDK源码 Java集合框架源码解读(1)——ArrayList、LinkedList和Vector Java集合框架源码解读(2)——HashMap Java集合框架源码解读(3)——...
b)接口的动态代理方式 SqlMapConfig.xml文件说 2.Mybatis介绍 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到...
{1}Java基础}{17}{chapter.1} {1.1}基本语法}{17}{section.1.1} {1.2}数字表达方式}{17}{section.1.2} {1.3}补码}{19}{section.1.3} {1.3.1}总结}{23}{subsection.1.3.1} {1.4}数据类型}{23}{section.1.4} {...
108. Shortcut when printing from a Java Agent 278 109. Lotus Script: Write # statement 279 110. Lotus Script: Input # statement 280 111. 使用代理生成 XML 284 112. 使用视图生成 XML 286 113. 执行算术...
MySQL入Ar ]很简单学习笔记李国华.dox Oracle查看表结构.txt SQL作业代理禁用.txt sql.txt SQL-Transaction事物一起执行.txt sq和oracle的区别.txt sysobjects中type字段值意思txt W3School例句.txt 按照中文首字母...
031505_【第15章:Java反射机制】_动态代理笔记.pdf 031506_【第15章:Java反射机制】_工厂设计模式笔记.pdf 031601_【第16章:Annotation】_系统内建Annotation笔记.pdf 031602_【第16章:Annotation】_自定义...
Java多线程 基础学习笔记 / 学习静态代理模式-附件资源
我的Java学习笔记 初步打造在线最佳的Java学习笔记,笔记内容主要是对一些基础特性和编程细节进行总结整理,适合了解Java基础语法,想进一步深入学习的人 含博客讲解和二进制实例,采用maven构建,分模块学习,涉及...
内容: Spring资源管理 Spring表达式语言 ...AOP切面编程-代理功能的加强 Spring与JMS消息组件 Spring与WebService Spring与Redis数据库 JDBC操作模板 Spring事务管理 SpringDataJPA SpringMVC SpringSecurity
学习笔记 数据结构 Java (最终基于CAS实现) Spring Mybatis Zookeeper 数据库 Linux 大数据 协议 代码质量 画图工具 (在线,支持流程图、思维导图、原型图、UML、网络拓扑图等) ##Web转App工具 We5X HBuilder 数据...