java动态代理和cglib动态代理

动态代理应用广泛,Spring,Struts等框架很多功能是通过动态代理,或者进一步封装来实现的。

常见的动态代理模式实现有Java API提供的动态代理和第三方开源类库CGLIB动态代理。

Java API提供的动态代理是基于类反射实现的,用到的类有:

java.lang.reflect.InvocationHandler;

java.lang.reflect.Method;

java.lang.reflect.Proxy;

其实现是通过Proxy类的newProxyInstance()方法产生代理对象。自定义动态代理类需要实现InvocationHandler接口,该接口只有一个invoke()方法。

CGLIB是通过生成java 字节码从而动态的产生代理对象,因此需要字节码解析处理的依赖asm类库,字节码动态生成的代理对象实际上是继承了真实主题类的。这种实现方式需要导入cglib和asm的类库。下面用到的例子是cglib-2.2.2.jar, asm-3.3.1.jar。cglib使用了MethodInterceptor,其中的方法是intercept(),这是拦截的概念,很容易就想到了Struts2的拦截器。

比较之下,Java API提供的动态代理需要面向接口,产生代理对象,因此真实主题实现类必须实现了接口才可以。而CGLIB不需要面向接口,可以代理简单类,但由于动态代理对象是继承真实主题实现类的,因此要求真实主题实现类不能是final的。

下面是实现的例子。

首先,为了看到动态代理可以根据不同类动态产生不同代理的效果,我们新建两个接口,及其实现类。

package leon.aj.dynproxy.target;  
  
public interface Hello {  
    public String sayHello(String name);  
}

实现类:

package leon.aj.dynproxy.target;  
  
public class HelloImpl implements Hello {  
    @Override  
    public String sayHello(String name) {  
        String s = "Hello, "+name;  
        System.out.println(this.getClass().getName()+"->"+s);  
        return s;  
    }  
}

另一接口和实现类:

package leon.aj.dynproxy.target;  
  
public interface UserDao {  
    public boolean login(String username,String password);  
}
package leon.aj.dynproxy.target;  
  
public class UserDaoImpl implements UserDao {  
    @Override  
    public boolean login(String username, String password) {  
        String user = "("+username+","+password+")";  
        System.out.println(this.getClass().getName()+"-> processing login:"+user);  
        return true;  
    }  
}

应用Java API实现的动态代理类:

package leon.aj.dynproxy.java;  
  
import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
import java.lang.reflect.Proxy;  
  
public class JavaDynProxy implements InvocationHandler{  
    private Object target;  
    public Object getProxyInstance(Object target){  
        this.target = target;  
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),   
                target.getClass().getInterfaces(), this);  
    }  
      
    @Override  
    public Object invoke(Object proxy, Method method, Object[] args)  
            throws Throwable {  
        Object result = null;  
        System.out.println("before target method...");  
        result = method.invoke(target, args);  
        System.out.println("after target method...");  
        return result;  
    }  
}

测试:

package leon.aj.dynproxy.java;  
  
import leon.aj.dynproxy.target.Hello;  
import leon.aj.dynproxy.target.HelloImpl;  
import leon.aj.dynproxy.target.UserDao;  
import leon.aj.dynproxy.target.UserDaoImpl;  
  
public class TestJavaProxy {  
    public static void main(String[] args) {  
        JavaDynProxy proxy = new JavaDynProxy();  
        Hello hello = (Hello)proxy.getProxyInstance(new HelloImpl());  
        String s = hello.sayHello("Leon");  
        System.out.println(s);  
          
        UserDao userDao = (UserDao) proxy.getProxyInstance(new UserDaoImpl());  
        userDao.login("Leon", "1234");  
        System.out.println(userDao.getClass().getName());  
    }  
}

下面是采用cglib实现的例子:

package leon.aj.dynproxy.cglib;  
  
import java.lang.reflect.Method;  
  
import net.sf.cglib.proxy.Enhancer;  
import net.sf.cglib.proxy.MethodInterceptor;  
import net.sf.cglib.proxy.MethodProxy;  
  
public class CglibProxy implements MethodInterceptor {  
    private Object target;    
      
    public Object getProxyInstance(Object target) {    
        this.target = target;  
        Enhancer enhancer = new Enhancer();    
        enhancer.setSuperclass(this.target.getClass());    
        enhancer.setCallback(this);  // call back method  
        return enhancer.create();  // create proxy instance  
    }    
      
    @Override  
    public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {  
        System.out.println("before target method...");  
        Object result = proxy.invokeSuper(target, args);  
        System.out.println("after target method...");  
        return result;  
    }  
}

测试类:

package leon.aj.dynproxy.cglib;  
  
import leon.aj.dynproxy.target.Hello;  
import leon.aj.dynproxy.target.HelloImpl;  
import leon.aj.dynproxy.target.UserDaoImpl;  
  
public class TestCiglib {  
    public static void main(String[] args) {  
        CglibProxy proxy = new CglibProxy();  
        Hello hello = (Hello) proxy.getProxyInstance(new HelloImpl());  
        System.out.println(hello.sayHello("Leon"));  
        UserDaoImpl userDao = (UserDaoImpl) proxy.getProxyInstance(new UserDaoImpl());  
        userDao.login("Leon", "1234");  
        System.out.println(userDao.getClass().getSuperclass());//看动态代理实例的父类  
    }  
}
时间: 2024-11-02 03:58:56

java动态代理和cglib动态代理的相关文章

关于JDK动态代理和CGLIB动态代理

1. 代理模式 一句话总结:为其他对象提供一种代理以控制对这个对象的访问.千篇一律的介绍:代理模式是常用的java设计模式,他的特征是代理类与委托类(或目标类)有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务. 按照代理的创建时期,代理类可以分为两种. 静态代理:由程序员创建或特定工具

spring aop原理 JDK动态代理和CGLIB动态代理

Spring的两大特性是IOC和AOPIOC负责将对象动态的注入到容器,从而达到一种需要谁就注入谁,什么时候需要就什么时候注入的效果.理解spring的ioc也很重要.但是今天主要来和大家讲讲aop.AOP 广泛应用于处理一些具有横切性质的系统级服务,AOP 的出现是对 OOP 的良好补充,用于处理系统中分布于各个模块的横切关注点,比如事务管理.日志.缓存等等. AOP实现的关键在于AOP框架自动创建的AOP代理.AOP代理主要分为静态代理和动态代理, 静态代理的代表为AspectJ:动态代理则

jdk动态代理和cglib动态代理底层实现原理详细解析(cglib动态代理篇)

代理模式是一种很常见的模式,关于底层原理网上看到很多的有关的讲解,但看了一些都觉得比较粗略,很多时候把底层代码copy下来也不大讲解,感觉不如自己详细的写上一篇.本文将以非常详细的说明来分析cglib动态代理底层的实现原理,篇幅较长,但是每个核心方法代码中每步都有说明.还请耐心阅读 1. 举例 使用cglib代理需要引入两个包,maven的话包引入如下 <!-- https://mvnrepository.com/artifact/cglib/cglib --> <dependency&

深入探索spring技术内幕(六): JDK动态代理和cglib生成代理

[ JDK生成代理 ] JDK中给我们提供了一个Proxy类可以动态的给我们生成代理. 假定我们要做一个权限管理系统, 需要控制用户对某一个方法的访问. 如果user为null, 那么不让用户访问save方法. ① 接口类: PersonService public interface PersonService { public void save(); } ② 实现类: PersonServiceImpl public class PersonServiceImpl implements P

JDK动态代理和CGLIB动态代理

转载自http://www.itzhai.com/java-dong-tai-dai-li-zhi-jdk-dong-tai-dai-li-he-cglib-dong-tai-dai-li-mian-xiang-qie-mian-bian-cheng-aop-yuan-li.html 静态代理 静态代理相对来说比较简单,无非就是聚合+多态: 参考:设计模式笔记 – Proxy 代理模式 (Design Pattern) 动态代理 我们知道,通过使用代理,可以在被代理的类的方法的前后添加一些处理方

JDK动态代理和CGLIB动态代理+源码下载

在上一篇文章-java代理详解讲解实现机制,一种是继承另外一种是组合,而且通过做实现也证明使用组合的方式更加的灵活.之后提到了代理的两种种类,一种是静态代理,另外一种是动态代理.上一篇文件中着重介绍的是静态代理(相对于动态代理很容易理解).这一片文章就接着介绍动态代理. 动态代理实现的最终效果:通过以一个统一的方式实现对任意的接口/类的代理.相比较静态代理而言,我们可以不用再无限制的增加代理类,不用再写许多重复的代码.很符合面向对象设计原则中的"开闭原则":对修改关闭,对扩展开放. 动

【Spring】AOP之JDK动态代理和CGLib动态代理

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 一.JAVA动态代理  1.1 代理模式         代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务. 按照代理的创

Spring 静态代理+JDK动态代理和CGLIB动态代理

代理分为两种:静态代理 动态代理 静态代理:本质上会在硬盘上创建一个真正的物理类 动态代理:本质上是在内存中构建出一个类. 如果多个类需要进行方法增强,静态代理则需要创建多个物理类,占用磁盘空间.而动态代理则是在内存中创建,不会对磁盘进行影响. 静态代理和JDK动态代理需要有接口. CGLIB动态代理无需有接口的情况下进行代理.实质:内存中构建出了目标类型的子类. JDK动态代理是JDK提供的,CGLIB动态代理是Spring提供的. 代理模式的三个组件:抽象主题 真实主题 代理主题 静态代理:

jdk动态代理和cglib动态代理的区别

CGLIB代理: CGLIB底层:使用字节码处理框架ASM,来转换字节码并生成新的类. CGLIB(CODE GENERLIZE LIBRARY)代理是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的所有方法,所以该类或方法不能声明称final的. 如果目标对象实现了接口,可以强制使用CGLIB实现代理. 如果目标对象没有实现接口,则默认会采用CGLIB代理: 为什么jdk动态代理必须基于接口 原因如下: 1.生成的代理类继承了Proxy,由于java是单继承,所以只能实现接口,通过接口