CGlib和JDK动态代理

一、CGlib动态代理

JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了。CGLib采用了非常底层的1:字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用2:方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。

字节码技术:参考:http://note.youdao.com/noteshare?id=13453e8d815d3102938a02881b6f418f&sub=E56D1E6223FC4CA8BF072CD045301EFA

CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。同时,由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理。

简单的实现举例:

这是一个需要被代理的类,也就是父类,通过字节码技术创建这个类的子类,实现动态代理。

[java]view plain copy

1.public class SayHello {

2.   public void say(){

3.    System.out.println("hello everyone");

4.   }

5.  }

该类实现了创建子类的方法与代理的方法。getProxy(SuperClass.class)方法通过入参即父类的字节码,通过扩展父类的class来创建代理对象。intercept()方法拦截所有目标类方法的调用,obj表示目标类的实例,method为目标类方法的反射对象,args为方法的动态入参,proxy为代理类实例。proxy.invokeSuper(obj, args)通过代理类调用父类中的方法。

[java]view plain copy

1.public class CglibProxy implements MethodInterceptor{

2.   private Enhancer enhancer = new Enhancer();

3.   public Object getProxy(Class clazz){

4.    //设置需要创建子类的类

5.    enhancer.setSuperclass(clazz);

6.    enhancer.setCallback(this);

7.    //通过字节码技术动态创建子类实例

8.    return enhancer.create();

9.   }

10.
 //实现MethodInterceptor接口方法

11.
 public Object intercept(Object obj, Method method, Object[] args,

12.
   MethodProxy proxy) throws Throwable {

13.
  System.out.println("前置代理");

14.
  //通过代理类调用父类中的方法

15.
  Object result = proxy.invokeSuper(obj, args);

16.
  System.out.println("后置代理");

17.
  return result;

18.
 }

19.
}

具体实现类:

[java]view plain copy

1.public class DoCGLib {

2.   public static void main(String[] args) {

3.    CglibProxy proxy = new CglibProxy();

4.    //通过生成子类的方式创建代理类

5.    SayHello proxyImp = (SayHello)proxy.getProxy(SayHello.class);

6.    proxyImp.say();

7.   }

8.  }

输出结果:

[plain]view plain copy

1.前置代理

2.  hello everyone

3.  后置代理

二、JDK动态代理

使用动态代理的五大步骤

1.通过实现InvocationHandler接口来自定义自己的InvocationHandler;

2.通过Proxy.getProxyClass获得动态代理类

3.通过反射机制获得代理类的构造方法,方法签名为getConstructor(InvocationHandler.class)

4.通过构造函数,获得代理对象,并将自定义的InvocationHandler实例对象传为参数传入

5.通过代理对象调用目标方法

publicclass ObjectProxy implements
InvocationHandler {

Object target = null;

List<BeforeAdvice> beforeList = new ArrayList<BeforeAdvice>();

List<AfterAdvice> afterList = new ArrayList<AfterAdvice>();

public ObjectProxy() {

super();

// TODO Auto-generated constructor stub

}

public ObjectProxy(Object target) {

super();

this.target = target;

try{

//解析advice.xml中所有的前置通知--得到class的值--->通过反射得到类的对象

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

DocumentBuilder db = dbf.newDocumentBuilder();

Document doc = db.parse("src//advice.xml");

//遍历前置通知

NodeList beforeNodeList = doc.getElementsByTagName("beforeAdvice");

for(int i=0;i<beforeNodeList.getLength();i++){

Element beforeElement =(Element) beforeNodeList.item(i);

String classValue = beforeElement.getAttribute("class"); //类的完整路径

Class clz = Class.forName(classValue);

BeforeAdvice obj = (BeforeAdvice)clz.newInstance();

beforeList.add(obj);

}

//遍历后置通知

NodeList afterNodeList = doc.getElementsByTagName("afterAdvice");

for(int i=0;i<afterNodeList.getLength();i++){

Element afterElement =(Element) afterNodeList.item(i);

String classValue = afterElement.getAttribute("class"); //类的完整路径

Class clz = Class.forName(classValue);

AfterAdvice obj = (AfterAdvice)clz.newInstance();

afterList.add(obj);

}

}catch(Exception e){

e.printStackTrace();

}

}

/**

* 伪装成目标类之后,要执行的方法

*/

@Override

public Object invoke(Object proxy, Method method, Object[] args)

throws Throwable {

//短信验证

for(BeforeAdvice bf:beforeList){

//对method目标方法进行判断,执行响应的前置切面业务

bf.Before();

}

//目标方法

Object result = method.invoke(target, args);

//日志记录

for(AfterAdvice af:afterList){

//对method目标方法进行判断,执行响应的后置切面业务

af.After();

}

return result;

}

/**

* 获得代理类的对象

* @param obj

* @return

*/

public
static  Object getProxyBean(Object obj){

return Proxy.newProxyInstance(obj.getClass().getClassLoader(),

obj.getClass().getInterfaces(),new ObjectProxy(obj));

}

}

publicstatic
void main(String[] args) {

Idog dog = (Idog)ObjectProxy.getProxyBean(new Dog());

dog.say();

}

时间: 2024-08-30 13:42:36

CGlib和JDK动态代理的相关文章

Cglib和jdk动态代理的区别

动态代理解决了方法之间的紧耦合, IOC解决了类与类之间的紧耦合! Cglib和jdk动态代理的区别? 1.Jdk动态代理:利用拦截器(必须实现InvocationHandler)加上反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理 2. Cglib动态代理:利用ASM框架,对代理对象类生成的class文件加载进来,通过修改其字节码生成子类来处理 什么时候用cglib什么时候用jdk动态代理? 1.目标对象生成了接口 默认用JDK动态代理 2.如果目标对象使

zbb20180930 代理模式 -静态代理-jdk动态代理-cglib动态代理

CGLIB与JDK动态代理区别 区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理.而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理. 1.如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP 2.如果目标对象实现了接口,可以强制使用CGLIB实现AOP 3.如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB

Java进阶之 JDK动态代理与Cglib动态代理

一.动态代理概述: 与静态代理对照(关于静态代理的介绍 可以阅读上一篇:JAVA设计模式之 代理模式[Proxy Pattern]), 动态代理类的字节码是在程序运行时由Java反射机制动态生成. 注意: 1.AspectJ是采用编译时生成AOP代理类,具有更好的性能,但是需要使用特定的编译器进行处理 2.Spring AOP采用运行时生成AOP代理类,无需使用特定编译器进行处理,但是性能相对于AspectJ较差 二.JDK动态代理 [对有实现接口的对象做代理] 1.JDK动态代理中 需要了解的

Java学习之:JDK动态代理与CGLIB动态代理

代理的概念:简单的理解就是通过为某一个对象创建一个代理对象,我们不直接引用原本的对象,而是由创建的代理对象来控制对原对象的引用. 动态代理:是指在程序运行时由Java反射机制动态生成,无需手动编写代码.动态代理不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java反射机制可以生成任意类型的动态代理类. 代理原理:代理对象内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象.同时,代理对象可以在执行真实对象操作时,附加其他的操作

Spring AOP详解 、 JDK动态代理、CGLib动态代理

AOP是Aspect Oriented Programing的简称,面向切面编程.AOP适合于那些具有横切逻辑的应用:如性能监测,访问控制,事务管理以及日志记录.AOP将这些分散在各个业务逻辑中的代码通过横向切割的方式抽取到一个独立的模块中. 一.AOP术语 1.连接点(Joinpoint) 程序执行的某个特定位置:如类开始初始化之前.类初始化之后.类某个方法调用前.调用后等:一个类或一段程序代码拥有一些具有边界性质的特定点,这些代码中的特定点就成为“连接点”,Spring仅支持方法的连接点,即

AOP学习心得&amp;jdk动态代理与cglib比较

什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入封装.继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合.当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力.也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系.例如日志功能.日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无

java 静态代理 JDK动态代理 Cglib动态代理

下面以一个简单的银行账户为例讲述讲述动态代理. 设计一个银行账户类,包含用户的账户余额,实现查询和更新余额功能 这个系统用了一段时间,有客户要求对账说账户余额给弄错了?因为上面没有存取款记录,最后银行不认账,客户收到了损失.银行为了避免这种现象再次发生,决定对这个系统进行修改,但是因为bankAccount太过复杂,希望在不修改bankAccount的情况下,增加日志功能. 静态代理 使用静态代理解决上面的问题. 银行要求所有模块都需要添加日志功能,这对苦逼的程序员来说真的是一个不小的工作量啊,

重温Spring之旅5——AOP代理对象、JDK动态代理、使用cglib生产代理

AOP--代理对象 代理模式:代理模式的英文叫做Proxy或Surrogate,中文都可译为"代理",所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 抽象主题角色:声明了真实主题和代理主题的共同接口,这样一来在任何可以使用真实主题的地方都可以是使用代理主题. 代理主题(Proxy)角色:代理主题角色内部含有对真实主题的引用,从而可以在任何时候操作真实主题对象:

JDK动态代理与CGLIB动态代理区别

JDK动态代理 只能代理实现了接口的类 没有实现接口的类不能实现JDK的动态代理 CGLIB动态代理 针对类来实现代理的 对指定目标类产生一个子类,通过方法拦击技术拦截所有父类方法的调用 使用Cglib实现动态代理 package com.imooc.cglib; public class Train {  public void move(){   System.out.println("火车行驶中");  } } import java.lang.reflect.Method; i