【转载】Java动态代理

转自:http://blog.csdn.net/heyutao007/article/details/49738887

AOP的拦截功能是由java中的动态代理来实现的。说白了,就是在目标类的基础上增加切面逻辑,生成增强的目标类(该切面逻辑或者在目标类函数执行之前,或者目标类函数执行之后,或者在目标类函数抛出异常时候执行。不同的切入时机对应不同的Interceptor的种类,如BeforeAdviseInterceptor,AfterAdviseInterceptor以及ThrowsAdviseInterceptor等)。

那么动态代理是如何实现将切面逻辑(advise)织入到目标类方法中去的呢?下面我们就来详细介绍并实现AOP中用到的两种动态代理。

AOP的源码中用到了两种动态代理来实现拦截切入功能:jdk动态代理和cglib动态代理。两种方法同时存在,各有优劣。jdk动态代理是由Java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。总的来说,反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。还有一点必须注意:jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。由此可以看出,jdk动态代理有一定的局限性,cglib这种第三方类库实现的动态代理应用更加广泛,且在效率上更有优势。。

1、定义接口和实现

[java] view plain copy print?

  1. package com.meituan.hyt.test3.service;
  2. public interface UserService {
  3. public String getName(int id);
  4. public Integer getAge(int id);
  5. }

[java] view plain copy print?

  1. package com.meituan.hyt.test3.service.impl;
  2. import com.meituan.hyt.test3.service.UserService;
  3. public class UserServiceImpl implements UserService {
  4. @Override
  5. public String getName(int id) {
  6. System.out.println("------getName------");
  7. return "Tom";
  8. }
  9. @Override
  10. public Integer getAge(int id) {
  11. System.out.println("------getAge------");
  12. return 10;
  13. }
  14. }

2、jdk动态代理实现

[java] view plain copy print?

  1. package com.meituan.hyt.test3.jdk;
  2. import java.lang.reflect.InvocationHandler;
  3. import java.lang.reflect.Method;
  4. public class MyInvocationHandler implements InvocationHandler {
  5. private Object target;
  6. MyInvocationHandler() {
  7. super();
  8. }
  9. MyInvocationHandler(Object target) {
  10. super();
  11. this.target = target;
  12. }
  13. @Override
  14. public Object invoke(Object o, Method method, Object[] args) throws Throwable {
  15. if("getName".equals(method.getName())){
  16. System.out.println("++++++before " + method.getName() + "++++++");
  17. Object result = method.invoke(target, args);
  18. System.out.println("++++++after " + method.getName() + "++++++");
  19. return result;
  20. }else{
  21. Object result = method.invoke(target, args);
  22. return result;
  23. }
  24. }
  25. }

[java] view plain copy print?

  1. package com.meituan.hyt.test3.jdk;
  2. import com.meituan.hyt.test3.service.UserService;
  3. import com.meituan.hyt.test3.service.impl.UserServiceImpl;
  4. import java.lang.reflect.InvocationHandler;
  5. import java.lang.reflect.Proxy;
  6. public class Main1 {
  7. public static void main(String[] args) {
  8. UserService userService = new UserServiceImpl();
  9. InvocationHandler invocationHandler = new MyInvocationHandler(userService);
  10. UserService userServiceProxy = (UserService)Proxy.newProxyInstance(userService.getClass().getClassLoader(),
  11. userService.getClass().getInterfaces(), invocationHandler);
  12. System.out.println(userServiceProxy.getName(1));
  13. System.out.println(userServiceProxy.getAge(1));
  14. }
  15. }

运行结果

++++++before getName++++++

------getName------

++++++after getName++++++

Tom

------getAge------

10

3、cglib动态代理实现

Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类,使用CGLIB即使代理类没有实现任何接口也可以实现动态代理功能。CGLIB具有简单易用,它的运行速度要远远快于JDK的Proxy动态代理:

CGLIB的核心类:

net.sf.cglib.proxy.Enhancer – 主要的增强类

net.sf.cglib.proxy.MethodInterceptor – 主要的方法拦截类,它是Callback接口的子接口,需要用户实现

net.sf.cglib.proxy.MethodProxy – JDK的java.lang.reflect.Method类的代理类,可以方便的实现对源对象方法的调用,如使用:

Object o = methodProxy.invokeSuper(proxy, args);//虽然第一个参数是被代理对象,也不会出现死循环的问题。

net.sf.cglib.proxy.MethodInterceptor接口是最通用的回调(callback)类型,它经常被基于代理的AOP用来实现拦截(intercept)方法的调用。这个接口只定义了一个方法

public Object intercept(Object object, java.lang.reflect.Method method,

Object[] args, MethodProxy proxy) throws Throwable;

第一个参数是代理对像,第二和第三个参数分别是拦截的方法和方法的参数。原来的方法可能通过使用java.lang.reflect.Method对象的一般反射调用,或者使用

net.sf.cglib.proxy.MethodProxy对象调用。net.sf.cglib.proxy.MethodProxy通常被首选使用,因为它更快。

[java] view plain copy print?

  1. package com.meituan.hyt.test3.cglib;
  2. import net.sf.cglib.proxy.MethodInterceptor;
  3. import net.sf.cglib.proxy.MethodProxy;
  4. import java.lang.reflect.Method;
  5. public class CglibProxy implements MethodInterceptor {
  6. @Override
  7. public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
  8. System.out.println("++++++before " + methodProxy.getSuperName() + "++++++");
  9. System.out.println(method.getName());
  10. Object o1 = methodProxy.invokeSuper(o, args);
  11. System.out.println("++++++before " + methodProxy.getSuperName() + "++++++");
  12. return o1;
  13. }
  14. }

[java] view plain copy print?

  1. package com.meituan.hyt.test3.cglib;
  2. import com.meituan.hyt.test3.service.UserService;
  3. import com.meituan.hyt.test3.service.impl.UserServiceImpl;
  4. import net.sf.cglib.proxy.Enhancer;
  5. public class Main2 {
  6. public static void main(String[] args) {
  7. CglibProxy cglibProxy = new CglibProxy();
  8. Enhancer enhancer = new Enhancer();
  9. enhancer.setSuperclass(UserServiceImpl.class);
  10. enhancer.setCallback(cglibProxy);
  11. UserService o = (UserService)enhancer.create();
  12. o.getName(1);
  13. o.getAge(1);
  14. }
  15. }

运行结果:

++++++before CGLIB$getName$0++++++

getName

------getName------

++++++before CGLIB$getName$0++++++

++++++before CGLIB$getAge$1++++++

getAge

------getAge------

++++++before CGLIB$getAge$1++++++

时间: 2024-10-06 11:57:44

【转载】Java动态代理的相关文章

【转载】Java 动态代理

Java 动态代理 本文为 Android 开源项目源码解析 公共技术点中的 动态代理 部分项目地址:Jave Proxy,分析的版本:openjdk 1.6,Demo 地址:Proxy Demo分析者:Caij,校对者:Trinea,校对状态:完成 1. 相关概念 1.1 代理 在某些情况下,我们不希望或是不能直接访问对象 A,而是通过访问一个中介对象 B,由 B 去访问 A 达成目的,这种方式我们就称为代理.这里对象 A 所属类我们称为委托类,也称为被代理类,对象 B 所属类称为代理类.代理

java动态代理学习笔记

没事的时候翻看lang.reflect包下的代码,发现有两部分内容:涉及反射和动态代理. 很多地方都可以看到动态代理的影子,只是一直没仔细看下. 在学习之前,先提出几个问题,带着问题来看代码: 1.什么是动态代理? 2.为什么使用动态代理? 3.使用它有哪些好处? 4.哪些地方需要动态代理? --------------------分隔线----------------------------- 和动态代理有关的有两个类 1.interface InvocationHandler Object

(转)Java动态代理与CGLib代理

本文通过spring aop的代理实现简述了java动态代理和cglib的区别,有助于理解java的代理模式 转载自:http://www.iteye.com/topic/182654 Java代码 <br>public class UserDAOImpl{ <br><br>    public void save() { <br>        // TODO Auto-generated method stub <br>        Sys

Java动态代理 深度详解

代理模式是设计模式中非常重要的一种类型,而设计模式又是编程中非常重要的知识点,特别是在业务系统的重构中,更是有举足轻重的地位.代理模式从类型上来说,可以分为静态代理和动态代理两种类型. 今天我将用非常简单易懂的例子向大家介绍动态代理的两种类型,接着重点介绍动态代理的两种实现方式(Java 动态代理和 CGLib 动态代理),最后深入剖析这两种实现方式的异同,最后说说动态代理在我们周边框架中的应用. 在开始之前,我们先假设这样一个场景:有一个蛋糕店,它们都是使用蛋糕机来做蛋糕的,而且不同种类的蛋糕

理解java动态代理

java动态代理是java语言的一项高级特性.在平时的项目开发中,可能很难遇到动态代理的案例.但是动态代理在很多框架中起着不可替代的作用,例如Spring的AOP.今天我们就聊一聊java动态代理的实现原理. jdk对于动态代理的支持主要依赖于两个类:Proxy和InvocationHandler.我们先看一下类图. Subject类是主题类,定义了我要做什么.我们需要代理的类即实现Subject接口的RealSubject. 1.InvocationHandler InvocationHand

java动态代理的实现

动态代理作为代理模式的一种扩展形式,广泛应用于框架(尤其是基于AOP的框架)的设计与开发,本文将通过实例来讲解Java动态代理的实现过程. 友情提示:本文略有难度,读者需具备代理模式相关基础知识,. 通常情况下,代理模式中的每一个代理类在编译之后都会生成一个class文件,代理类所实现的接口和所代理的方法都被固定,这种代理被称之为静态代理(Static Proxy).那么有没有一种机制能够让系统在运行时动态创建代理类?答案就是本文将要介绍的动态代理(Dynamic Proxy).动态代理是一种较

java动态代理机制

首先了解代理设计模式,其思想是为其他对象提供一种代理以控制对这个对象的访问. java动态代理就是遵循这种思想,spring中的AOP实现原理就是java的动态代理. 在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface).另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的. 每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通

java动态代理

要想了解Java动态代理,首先要了解什么叫做代理,熟悉设计模式的朋友一定知道在Gof总结的23种设计模式中,有一种叫做代理(Proxy)的对象结构型模式,动态代理中的代理,指的就是这种设计模式. 在我看来所谓的代理模式,和23种设计模式中的"装饰模式"是一个东西.23种设计模式中将它们作为两种模式,网上也有些文章讲这两种模式的异同,从细节来看,确实可以人为地区分这两种模式,但是抽象到一定高度后,我认为这两种模式是完全一样的.因此学会了代理模式,也就同时掌握了装饰模式. 代理模式 代理模

java 动态代理示例,带主要注释

Java proxy是基于反射,仅仅支持基于接口的动态代理. java 动态代理是一切架构的基础,必须了解. 废话少说,先上代码获得感性认识. 示例代码有主要注释. 接口: public interface Subject { String hello(String name); void say();} 接口实现: public class ImpSubject implements Subject { @Override public String hello(String name){ r

java动态代理原理及解析

代理:设计模式 代理模式是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个真实对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 通过代理层这一中间层,有效的控制对于真实委托类对象的直接访问,同时可以实现自定义的控制策略(Spring的AOP机制),设计上获得更大的灵活性. java动态代理的类和接口(jdk1.6源码) 1,java.lang.reflect.Proxy:动态代理机制的主类,提供一组静态方法为一组接口动态的生成对