JAVA基础知识之JVM-——动态代理(AOP)
代理模式简介
在很多场景下,我们想使用一个类(通常是接口)A时,并不是直接使用这个类,而是通过另外一个类B去调用A的方法,这里的类B就是一个代理类。
有很多场景都会用到这种方法,例如假如创建类A需要很大的开销,我们会直接使用类B来代表类A。 又或者类A在远程主机上,我们没有权限直接调用A的方法,而代理类B却有权限,我们可以调用B从而访问到A。 又或者我们需要批量给A的方法加强一些功能,而我们没有权限修改A,或者修改A会导致其他关联的类因为耦合性需要修改,这时候我们也同样可以通过代理类B来增加功能。 这种间接访问A的方式就是一种非常常见的代理模式——通常我们只需要知道一个接口里提供了哪些方法,但并不需要方法细节,我们可以通过代理类来控制这些方法的调用,并满足例如前面提到的各种场景的功能要求。
动态代理
JAVA的代理模式大体上分为静态代理(编译期间就已经明确代理类及委托类的细节)和动态代理(在JVM中动态生成一个代理类,通过动态生成的代理类去访问委托类)。
动态代理也称为AOP模式,即面向切面编程。 实现AOP的方式有很多,目前主要有两种,一种是JDK自己实现的基于接口的动态代理,另一种是cglib方式,不需要强制实现接口。
本篇只简单介绍JDK自带的动态代理。
JDK动态代理
java动态代理主要涉及几个角色,目标类(接口-target),代理对象(proxy),处理器类(接口-InvocationHandler)。
实现原理大致是这样的,通过代理类proxy访问目标类target时,在JDK底层,会动态生成一个proxy类(其实是子类),同时让会让这个proxy类实现target接口,这个Proxy类包含一个InvocationHandler类型的成员变量,后面就会用处理器对象去初始化这个Proxy类对象。proxy中对target类所有的方法实现都交给InvocationHandler的实现类去处理,通过在proxy中重写target方法的实现,而在实现中直接调用InvocationHandler的invoke方法,这样就变成了我们调用代理proxy类执行target方法的时候,实际上是执行了InvocationHandler的invoke方法,而在invoke方法中,我们可以加入我们自己的逻辑,然后才调用真正的target中的方法。
整个过程可以用下面两段伪代码来模拟,
首先根据我们为proxy传入的参数(target所有接口方法,InvocationHandler实例),JDK会在底层动态地为我们创建一个代理类,代理类如下,
class Proxy0 extends Proxy implements target {
private Method m1;
//用InvocationHandler去初始化proxy, 后期就可以将proxy的代理的方法交给InvocationHandler去处理
public Proxy0(InvocationHandler handler) {
supper(hander)
}
public void setM1(Method m1) {
this.m1 = m1;
}
private void method1(Object para) {
this.hander.invoke(this, m1, new object[] {para});
}
}
这段代理类的动态生成过程都由JVM控制,我们不可见(当然可以通过特殊方式拿到)。可以看到代理类会实现目标类target的所有方法,但是实现类中是调用了InvocationHandler的invoke方法的,这个invoke方法是需要我们自己去实现的,一般类似这样,
class InvocationHandlerImpl implements InvocationHandler {
private Object target; @Override
public Object invoke(Object proxy, Method method, Object[] args) {
// 加入我们自己的代码
....
//调用目标类的真正方法
method.invoke(target, args);
//加入我们自己的代码
.....
}
关键点在于第2行和第8行,使用了反射执行了目标类的真正需要被代理的方法。
以上整个过程,就是proxy代理的实现原理。
下面这张图片借用了别人的博客

下面是一个简单的例子,演示JDK动态代理的用法,
定义一个Dog接口, JDK的动态代理是基于接口的,其他动态代理可以基于继承的方式。
package aop;
public interface Dog {
void info();
void run();
}
为接口写个实现类,
package aop;
public class GunDog implements Dog {
@Override
public void info() {
// TODO Auto-generated method stub
System.out.println("我是一只猎狗");
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("我奔跑迅速");
}
}
写个工具类,
package aop;
public class DogUtil {
public void method1() {
System.out.println("====this is method1====");
}
public void method2() {
System.out.println("====this is method2====");
}
}
关键点,写一个处理器,实现InvocationHandler接口,
在invoke中加上我们自己的逻辑,再调用真正的target的方法。
后续代理类在处理target的所有方法时,都会在底层调用invoke方法,即将调用交给invoke了
package aop; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; public class MyInvocationHandler implements InvocationHandler { private Object target; public void setTarget(Object target) {
this.target = target;
} @Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
DogUtil du = new DogUtil();
du.method1();
Object result = method.invoke(target, args);
du.method2();
return result;
} }
写一个工厂类获取proxy类实例,简化编程
package aop;
import java.lang.reflect.Proxy;
public class MyProxyFactory {
public static Object getProxy(Object target) {
MyInvocationHandler handler = new MyInvocationHandler();
handler.setTarget(target);
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler);
}
}
下面是测试类,
package aop;
public class Test {
public static void main(String[] args) {
Dog target = new GunDog();
Dog dog = (Dog)MyProxyFactory.getProxy(target);
dog.info();
dog.run();
}
}
执行结果如下,
代理开始。。。
我是一只猎狗
代理结束。。。
代理开始。。。
我奔跑迅速
代理结束。。。
reference
http://blog.csdn.net/luanlouis/article/details/24589193
JAVA基础知识之JVM-——动态代理(AOP)的更多相关文章
- Java基础之反射和动态代理
1,反射是依赖于Class对象,然后根据Class对象,去操作该类的资源的.Class对象是发射的基石! 问题1:人这类事物用什么表示?汽车这类事物用什么表示>计算机文件用什么表示?有如此多的事 ...
- Java基础加强-(注解,动态代理,类加载器,servlet3.0新特性)
1. Annotation注解 1.1. Annotation概述 Annotation是JDK 5.0以后提供对元数据的支持,可以在编译.加载和运行时被读取,并执行相应的处理.所谓Annota ...
- 《精通Spring4.X企业应用开发实战》读后感第七章(AOP基础知识、jdk动态代理,CGLib动态代理)
- java 基础知识学习 JVM虚拟机参数配置
1) 设置-Xms.-Xmx相等: 2) 设置NewSize.MaxNewSize相等: 3) 设置Heap size, PermGen space: Tomcat 的配置示例:修改%TOMCAT_H ...
- 学习Spring必学的Java基础知识(2)----动态代理
Spring AOP使用动态代理技术在运行期织入增强的代码,为了揭示Spring AOP底层的工作机理,有必要对涉及到的Java知识进行学习.Spring AOP使用了两种代理机制:一种是基于JDK的 ...
- JAVA基础知识|java虚拟机(JVM)
一.JVM简介 java语言是跨平台的,兼容各种操作系统.实现跨平台的基石就是虚拟机(JVM),虚拟机不是跨平台的,所以不同的操作系统需要安装不同的jdk版本(jre=jvm+类库:jdk=jre+开 ...
- Java基础知识:代理
一.代理的概念 动态代理技术是整个java技术中最重要的一个技术,它是学习java框架的基础,不会动态代理技术,那么在学习Spring这些框架时是学不明白的. 动态代理技术就是用来产生一个对象的代理对 ...
- 学习Spring必学的Java基础知识(1)----反射(转)
引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓"登高必自卑,涉远必自迩".以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系 ...
- 学习Spring必学的Java基础知识(1)----反射
引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓"登高必自卑,涉远必自迩".以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系 ...
- 沉淀,再出发:Java基础知识汇总
沉淀,再出发:Java基础知识汇总 一.前言 不管走得多远,基础知识是最重要的,这些知识就是建造一座座高楼大厦的基石和钢筋水泥.对于Java这门包含了编程方方面面的语言,有着太多的基础知识了,从最初的 ...
随机推荐
- J2EE MyBatis使用
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis .20 ...
- mysql 执行状态分析 show processlist
SHOW PROCESSLIST显示哪些线程正在运行.您也可以使用mysqladmin processlist语句得到此信息.如果您有SUPER权限,您可以看到所有线程.否则,您只能看到您自己的线程( ...
- 遇到could not find developer disk image 问题怎么解决
一般是设备的版本低于或者高于当前的xcode
- JAVA-面向对象-多态
多态 1.方法重载 2.方法重写 3.对象转型 4.抽象(可以定义类和方法) (关键字 abstract) ( 如: public abstract class robot )(不能修饰 ...
- 一个新人对JavaScript的内容简单介绍
JavaScript 1.基本的数据类型:字符串 小数 整数 时间日期 布尔型等. 2.变量: JS定义变量通通都是用var开头,var里面可以放任何东西(如:小数,整数,字符串,时间日期等等 ...
- JSP 使用框架frame
JSP使用框架放在<head>标签里面.如果放在<body>标签里面,用Tomcat打开,是不会显示的.
- C++初学者 const使用详解
关于C++中的const关键字的用法非常灵活,而使用const将大大改善程序的健壮性,参考了康建东兄的const使用详解一文,对其中进行了一些补充,写下了本文. 1. const常量 如: cons ...
- override与final
override 强调该函数是重写的父类的函数 final 指定该函数不能被重写 两者都是针对virtual 函数
- android 添加背景音乐
MediaPlayer mediaPlayer=MediaPlayer.create(MainActivity.this,R.raw.qiji); mediaPlayer.start();
- JAVA通过poi对Excel数据在(jsp+ssh)环境下导入导出
POI的下载与安装 请到网站http://www.apache.org/dyn/closer.cgi/poi/右击超链接2.5.1.zip下载压缩包poi-bin-2.5.1-final-20040 ...