最近看书,有两个地方提到了动态代理,一是在Head First中的代理模式,二是Spring AOP中的AOP。所以有必要补充一下动态代理的相关知识。

Spring采用JDK动态代理和CGLib动态代理的技术在运行期实现AOP。要使用JDK动态代理,目标类必须实现相应的接口,而CGLib不对目标类做任何限制,它通过动态生成目标子类的方式提供代理。JDK在创建代理对象时性能高于CGLib,而生成的代理对象的性能却比CGLib低,如果是singleton的代理,推荐使用CGLib动态代理。-----《Spring3.0就是这么简单p73》

Java在java.lang.reflect包中有自己的代理支持,利用这个包你可以在运行时动态地创建一个代理类,实现一个或者多个接口,并将方法的调用转发到你所指定的类。-----《Head First设计模式p474》

在设计模式中,代理的目的有很多种,包括将请求转发到远端主题、给创建开销大的对象对象提供代表等等;在Spring AOP中提到代理类,基本上是指在普通业务类的基础上实现日志、性能统计、事务的增强。下面所描述的内容也以Spring AOP为基础。

一、静态代理

静态代理是指在编译的时候就生成代理类,因此也成为编译时增强。

实现静态代理常用的方法是通过AspectJ,AspectJ 是一个基于 Java 语言的 AOP 框架,提供了强大的 AOP 功能,主要包含两个部分,第一个部分定义了如何表达、定义 AOP 编程中的语法规范;另一个部分是工具部分,包括编译器、调试工具等。

使用AspectJ的流程是先定义业务类,然后用AspectJ提供的工具生成代理类,在此不详细介绍,如要详细了解,请参考下面的文档链接。

二、动态代理

无需使用任何特殊命令对 Java 源代码进行编译,它采用运行时动态地、在内存中临时生成“代理类”的方式来生成代理。有以下两种使用使用动态代理的方式:

(1)CGLib动态代理

CGLIB(Code Generation Library),简单来说,就是一个高效的代码生成类库,底层是依靠ASM(开源的java字节码编辑类库)操作字节码实现的,性能比JDK强。在Spring AOP中,它在运行期间生成的代理对象是针对目标类扩展的子类。

(2)JDK动态代理

Spring AOP中建议使用JDK动态代理。此时其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理。

Spring到底选择那种代理模式?如果被代理的目标对象实现了至少一个接口,则会使用JDK动态代理,所有该目标类型实现的接口都将被代理。若该目标对象没有实现任何接口,则创建一个CGLIB代理。上说的是默认情况下,也可以手动配置一些选项使Spring采用CGLIB代理。 
org.springframework.transaction.interceptor.TransactionProxyFactoryBean是org.springframework.aop.framework. ProxyConfig的子类,所以可以参照ProxyConfig里的一些设置,将optimize和proxyTargetClass任意一个设置为true都可以强制Spring采用CGLIB代理。

下面重点介绍一下Java的动态代理技术:

java.lang.reflect.Proxy:这是 Java 动态代理机制的主类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。

// 方法 1: 该方法用于获取指定代理对象所关联的调用处理器
static InvocationHandler getInvocationHandler(Object proxy) // 方法 2:该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象
static Class getProxyClass(ClassLoader loader, Class[] interfaces) // 方法 3:该方法用于判断指定类对象是否是一个动态代理类
static boolean isProxyClass(Class cl) // 方法 4:该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
static Object newProxyInstance(ClassLoader loader, Class[] interfaces,
InvocationHandler h)

java.lang.reflect.InvocationHandler:这是调用处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。

// 该方法负责集中处理动态代理类上的所有方法调用。第一个参数既是代理类实例,第二个参数是被调用的方法对象,第三个方法是调用参数。调用处理器根据这三个参数进行预处理或分派到委托类实例上反射执行
Object invoke(Object proxy, Method method, Object[] args)

实现一个动态添加前后日志的全部逻辑:

package newjava;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//普通对象和代理对象都要实现的接口
interface PersonInterface
{
void meeting();
}
//普通对象
class Person implements PersonInterface
{
@Override
public void meeting() {
System.out.println("meeting...");
}
}
//代理处理器
class PersonHander implements InvocationHandler
{
Person person;
PersonHander(Person p)
{
person = p;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//进行前后织入
if (method.getName().equals("meeting"))
{
System.out.println("good morning before metting");
Object obj = method.invoke(person, args); //调用原始类的meeting方法
System.out.println("good afternoon after metting");
return obj;
}
return null;
} }
//测试类
public class ProxyTest {
public static void main(String[] args)
{
//普通对象
Person p = new Person();
//创建代理对象,必须转换为实现的接口
PersonInterface personProxy = (PersonInterface) Proxy.newProxyInstance(
p.getClass().getClassLoader(),
p.getClass().getInterfaces(),
new PersonHander(p)
      );
//调用被代理后的方法,其实就是invoke方法,参数:代理对象本身,meeting对应的Method对象、实际参数都会传递到invoke里面去
personProxy.meeting();
}
}

参考:

http://www.ibm.com/developerworks/cn/java/j-lo-springaopcglib/

http://www.cnblogs.com/phoebus0501/archive/2011/03/11/1980569.html

http://www.flyne.org/article/255

JAVA中的代理技术(静态代理和动态代理)的更多相关文章

  1. 动态代理的两种方式,以及区别(静态代理、JDK与CGLIB动态代理、AOP+IoC)

    Spring学习总结(二)——静态代理.JDK与CGLIB动态代理.AOP+IoC   目录 一.为什么需要代理模式 二.静态代理 三.动态代理,使用JDK内置的Proxy实现 四.动态代理,使用cg ...

  2. 代理模式(静态代理、JDK动态代理原理分析、CGLIB动态代理)

    代理模式 代理模式是设计模式之一,为一个对象提供一个替身或者占位符以控制对这个对象的访问,它给目标对象提供一个代理对象,由代理对象控制对目标对象的访问. 那么为什么要使用代理模式呢? 1.隔离,客户端 ...

  3. 第89节:Java中的反射技术

    第89节:Java中的反射技术 反射技术是动态的获取指定的类,和动态的调用类中的内容(没有类前就可以创建对象,将对象的动作完成,这就是动态的获取指定的类). 配置文件把具体实现的类名称定义到配置文件中 ...

  4. Java动态代理:一个面包店的动态代理帝国

    文章首发于[博客园-陈树义],点击跳转到原文大白话说Java动态代理:一个面包店的动态代理帝国 代理模式是设计模式中非常重要的一种类型,而设计模式又是编程中非常重要的知识点,特别是在业务系统的重构中, ...

  5. Java动态代理(三)——Cglib动态代理

    一.Cglib动态代理Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类,使用Cglib即使代理类没有实现任何接口也可以实现动态代理功能.而且,它的运行速度要远远快 ...

  6. Java中的多线程技术全面详解

    本文主要从整体上介绍Java中的多线程技术,对于一些重要的基础概念会进行相对详细的介绍,若有叙述不清晰或是不正确的地方,希望大家指出,谢谢大家:) 为什么使用多线程 并发与并行 我们知道,在单核机器上 ...

  7. Spring 的AOP底层实现技术:JDK和CGLIB动态代理

    Spring 的AOP实现技术之JDK的动态代理技术实例: 接口:IUserService (Spring的AOP是动态AOP,实现技术:JDK提供的动态代理和cglib代理,cglib它可以为没有实 ...

  8. Java 中不允许使用静态局部变量

    Java 中不允许使用静态局部变量

  9. 代理模式(Proxy)--动态代理(JDK)

    在是上一篇博客中实现了静态代理. 在上篇的结尾提到了一个问题: 思考:如果我们下需要对火车,自行车实现相同的代理,我们又该如何实现呢? 这篇博客就来解决这个问题: 解决这类问题需要用到动态代理技术,实 ...

  10. 性能优于JDK代理,CGLib如何实现动态代理

    按照代理的创建时期,代理类可以分为两种. 静态代理:由程序员创建或特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经存在了. 动态代理:在程序运行时,运用反射机制动态创建 ...

随机推荐

  1. 《Linux内核设计与实现》读书笔记

    http://www.cnblogs.com/wang_yb/tag/linux-kernel/

  2. C 语言 .h文件的作用

    C语言头文件的作用 最近在工作当中遇到了一点小问题,关于C语言头文件的应用问题,主要还是关于全局变量的定义和声明问题.学习C语言已经有好几年了,工作使用也近半年了,但是对于这部分的东西的确还没有深入的 ...

  3. Spark之路 --- Scala用JFreeChart画图表实例

    JFreeChart介绍 JFreeChart是JAVA平台上的一个开放的图表绘制类库.它完全使用JAVA语言编写,是为applications, applets, servlets 以及JSP等使用 ...

  4. 那些著名或非著名的iOS面试题-前编

    1.如何追踪app崩溃率,如何解决线上闪退 当iOS设备上的App应用闪退时,操作系统会生成一个crash日志,保存在设备上.crash日志上有很多有用的信息,比如每个正在执行线程的完整堆栈跟踪信息和 ...

  5. Team Queue

    Team Queue Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 2471   Accepted: 926 Descrip ...

  6. Codeforces Round 190 div.2 322C 321A Ciel and Robot

    唔...这题是数学题. 比赛时做出来,但题意理解错了,以为只要判断那点是不是在线上就行了,发现过不了样例就没提交. 思路:记录每一步的偏移,假设那点是在路径上的某步,然后回推出那一个周期的第一步,判断 ...

  7. 配置hibernate出现的错误一

    问题:2011-04-18 11:35:46,734 ERROR [org.hibernate.tool.hbm2ddl.SchemaUpdate] - could not complete sche ...

  8. [Android]Log打印

    package com.lurencun.android.system; import android.util.Log; public class ExLog { static final Stri ...

  9. python django第二弹

    每天晚上应该就这样坐着,然后把每天的东西做个总结,或大或小,有的人可能愿意把自己的东西保留在草稿箱,想想我还是把他写出来吧,前几次我发现又遇到了之前遇到的简单的问题,翻看自己之前写的几篇小日记,可以很 ...

  10. 机器学习之SVM(支持向量机)

    支持向量机(SVM)是当前非常流行的监督学习方法,其核心主要有两个: 构造一个极大边距分离器--与样例点具有最大可能距离的决策边界: 将在原输入空间中线性不可分的样例映射到高维空间中,从而进行线性分离 ...