最近看书,有两个地方提到了动态代理,一是在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. sqlserver 字符串相关函数

    http://www.cnblogs.com/jiajiayuan/archive/2011/06/16/2082488.html 以下所有例子均Studnet表为例:  计算字符串长度len()用来 ...

  2. 简简单单安装debian桌面工作环境

    linux一般给人的影响是对使用者的要求偏高, 使用者需要自行配置很多相应的系统工作参数,因此,从一定的程度上阻碍了用户去使用它.而本文所介绍的是, 使用者完全可以消除这个障碍,非常简单地安装好自己的 ...

  3. [Qt5] 减少dll依赖和大小(特别是webkit的大小和依赖)

    Qt5的依赖太多, 而且很dll非常大. 折腾了好久, 摸索了一些精简的方法. webkit是个非常蛋疼的东西, 依赖超多, 又很庞大. 所以需不需要webkit是完全不同的. 如何编译Qt5可以参考 ...

  4. 《Cortex-M0权威指南》之绪论

    转载请注明来源:cuixiaolei的技术博客 1.1 为什么要选择Cortex-M0 为了满足现代超低功耗微控制器和混合信号设备的需要,ARM推出了Cortex-M0处理器.Cortex-M0在保持 ...

  5. some words we should know

    2010年,芬兰艺术家Mikko Kuorinki做了一件独特的艺术品. 他在赫尔辛基的奇亚斯玛当代艺术博物馆(Kiasma museum),找了一堵墙,装了一个175 x 320cm的木架子,上面用 ...

  6. SQL Server 调优:set statistics profile on

    进行set statistics profile on 设置后 将会返回执行计划表,通过该表,可以理解语句执行的过程,了解SQL Server是否选择了正确的执行计划,进而确定调优方向! 1.返回表字 ...

  7. 1045 | error connecting to master 'slave_user@192.168.0.75:3306' - retry-time: 6

    mysql 主从复制问题整理   问题:      1045 | error connecting to master 'slave_user@192.168.0.75:3306' - retry-t ...

  8. Laravel 中查询 where 记录

    Laravel 的 Eloquent 使用 Between $query->whereBetween('age',[$from,$to]) 这是生成 And between ... and .. ...

  9. 纯jq编写增删改,弹出框

    <!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head>    < ...

  10. VSX规划Package文件

    VSX是VS扩展,可以针对不同项目编写插件,虽然接触VSX的时间并不多,但是当了解VSX后深刻感受到VSX的魅力. VSX的材料比较少,配置文件也很繁琐,当初我也走了不少弯路. 这篇文章将帮助您更好的 ...