`
bit1129
  • 浏览: 1069683 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

【Java语言】动态代理

    博客分类:
  • Java
 
阅读更多

 

JDK接口动态代理

JDK自带的动态代理通过动态的根据接口生成字节码(实现接口的一个具体类)的方式,为接口的实现类提供代理。被代理的对象和代理对象通过InvocationHandler建立关联

 

package com.tom;

import com.tom.model.User;
import com.tom.service.IUserService;
import com.tom.service.UserService;

import java.lang.reflect.*;

class JdkInvocationHandler<T> implements InvocationHandler {
   //target是被代理的对象,构造注入到InvocationHandler中 
   private T target;

    public JdkInvocationHandler(T target) {
        this.target = target;
    }
    //invoke方法由代理对象调用,其中的proxy即是代理对象(不是被代理的对象)
    //method和args是代理对象要执行的方法及其参数
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(String.format("Start to call %s", method.getName()));
        Object obj = method.invoke(this.target, args);
        System.out.println(String.format("End to call %s", method.getName()));
        return obj;
    }
}


public class JdkProxyTest {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {


        InvocationHandler h = new JdkInvocationHandler<IUserService>(new UserService());

        //****************第一种方法****************
        //获得JDK的Proxy类字节码,类型为com.sun.proxy.$Proxy0
        Class proxyClass = Proxy.getProxyClass(UserService.class.getClassLoader(), new Class[]{IUserService.class});

        //获得com.sun.proxy.$Proxy0还有InvocationHandler参数的构造方法
        Constructor proxyConstructor = proxyClass.getConstructor(InvocationHandler.class);

        //构造$Proxy0的实例
        IUserService service = (IUserService) proxyConstructor.newInstance(h);

        //调用$Proxy0的save方法,方法实现是将方法调用转到InvocationHandler.invoke的调用
        service.save(new User());


        //****************第二种方法****************
        //使用Proxy.newProxyInstance一步到位创建$Proxy0实例
        service = (IUserService) Proxy.newProxyInstance(UserService.class.getClassLoader(), new Class[]{IUserService.class}, h);
        service.save(new User());





    }
}

 

 

cglib类动态代理

cglib是一个开源项目! 是强大的,高性能字节码生成类库,它可以在运行期扩展Java类与实现Java接口。CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。通过使用CGLIB来为那些没有接口的类创建代理对象。

 

Spring AOP提供了JDK接口动态代理和基于cglib类代理两种方式。使用cglib代理时,需要在配置中显式指明要使用cglib代理

 

cglib通过运行时创建被代理类的子类的方式生成字节码,通过被代理类的子类提供代理功能。因此声明为final的类不能被代理

 

CGLIB类动态代理

package com.tom;

import com.tom.model.User;
import com.tom.service.IUserService;
import com.tom.service.UserService;
import net.sf.cglib.proxy.*;

import java.lang.reflect.Method;

class UserServiceMethodInterceptor1 implements MethodInterceptor {

    @Override
    /**
     *
     * @param o 代理对象,例如com.tom.service.UserService$$EnhancerByCGLIB$$9257af4@360771
     * @param method 被代理类定义的原始方法,比如UserService.save
     * @param objects   方法调用的参数列表
     * @param methodProxy 对method进行代理的方法,比如CGLIB$save$0
     * @return
     * @throws Throwable
     */
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

        //输出:MethodInterceptor is called ..save , CGLIB$save$0
        System.out.println("MethodInterceptor1 is called .." + method.getName() + " , " + methodProxy.getSuperName());

        //调动UserService的方法
        return methodProxy.invokeSuper(o, objects);
    }
}

class UserServiceMethodInterceptor2 implements MethodInterceptor {

    @Override
    /**
     *
     * @param o 代理对象,例如com.tom.service.UserService$$EnhancerByCGLIB$$9257af4@360771
     * @param method 被代理类定义的原始方法,比如UserService.save
     * @param objects   方法调用的参数列表
     * @param methodProxy 对method进行代理的方法,比如CGLIB$save$0
     * @return
     * @throws Throwable
     */
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

        //输出:MethodInterceptor is called ..save , CGLIB$save$0
        System.out.println("MethodInterceptor2 is called .." + method.getName() + " , " + methodProxy.getSuperName());

        //调动UserService的方法
        return methodProxy.invokeSuper(o, objects);
    }
}

public class CglibTest {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserService.class);
        enhancer.setClassLoader(UserService.class.getClassLoader());

        //Callback干啥的,Callback接口没有任何方法
        //MethodInterceptor接口继承了Callback接口,因此这里可以注入三个MethodInterceptor的实例
        enhancer.setCallbacks(new Callback [] {new UserServiceMethodInterceptor1(), new UserServiceMethodInterceptor2(), NoOp.INSTANCE});

        //过滤??
        enhancer.setCallbackFilter(new CallbackFilter() {

           @Override
            public int accept(Method method) { //UserService中定义的所有方法都要过滤一遍,比如save,delete,hashCode,equals,finalize等
                if (method.getName().equals("save")) {
                    return 0; //使用第一个拦截器(这里设置了两个Callback)进行拦截
                }
                if (method.getName().equals("delete")) {
                    return 1;
                }
                return 2; //使用第三个拦截器,不做任何拦截
            }
        });

        //创建代理类实例,因为代理类被代理类的子类,因此,需要考虑父类的构造
        IUserService proxyObj = (IUserService) enhancer.create();//调用父类的构造方法,create的重载方法可以调用指定参数的构造方法

        //代理对象调用方法
        proxyObj.save(new User());

        proxyObj.delete(new User());

        proxyObj.hashCode(); //不会调用拦截器

        System.out.println(proxyObj.getClass().getName());

    }
}

 

 

 

 

总结

cglib创建代理对象的速度比JDK动态代理慢几倍,代理对象调用方法执行时,cglib执行速度要比JDK快几倍,因此如果需要频繁的创建代理对象,可以使用JDK动态代理,如果代理对象是单例,考虑使用cglib代理

性能比较参考:http://exceptioneye.iteye.com/blog/1774631

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

    java Proxy 动态代理

    动态代理机制是Java语言提供的一种反射特性,主要用于实现AOP(面向切面编程)或者对现有接口的扩展与增强。 在Java中,动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口...

    java动态代理实例

    Java动态代理是Java语言提供的一种在运行时创建代理对象的技术,它允许我们为已存在的接口创建代理类,以便在调用真实目标对象的方法时添加额外的功能或行为。在这个实例中,我们将深入探讨Java动态代理的核心概念,...

    JAVA静态代理和动态代理

    在Java编程语言中,代理模式是一种设计模式,它允许我们为一个对象提供一个代理以控制对这个对象的访问。代理模式通常用于增加额外的功能或在访问原对象时进行额外的操作,比如日志记录、安全控制、性能度量等。Java...

    Java动态代理案例演示代码

    Java动态代理是Java语言提供的一种强大的机制,它允许在运行时创建具有特定接口的代理类对象,这些代理类对象能够对方法调用进行拦截和增强。动态代理在很多场景下非常有用,例如AOP(面向切面编程)、事件监听、...

    java语言反射与动态代理学习笔记2(动态代理部分)

    反射是Java语言的一个强大工具,它允许程序在运行时检查类、接口、字段和方法的信息,并能够动态地创建对象和调用方法。通过`Class`类、`Field`类、`Method`类以及`Constructor`类,我们可以获取类的信息并进行操作...

    java动态代理机制

    Java动态代理机制是Java语言提供的一种强大的功能,它允许在运行时创建代理对象来实现特定接口,从而可以灵活地扩展或增强已有代码的功能。在Java中,动态代理主要通过两个类来实现:`java.lang.reflect.Proxy` 和 `...

    Java动态代理helloworld

    在Java编程语言中,动态代理是一种强大的特性,它允许我们在运行时创建代理对象来扩展或增强已有类的功能。本篇文章将深入探讨Java动态代理的概念、原理以及如何通过一个简单的"Hello, World!"示例来理解它。 动态...

    java 动态代理 简单实例

    Java动态代理是Java语言提供的一种在运行时创建代理对象的技术,它允许我们为已存在的接口创建代理类,以便在调用方法时添加额外的功能或控制。动态代理在很多场景下非常有用,比如日志记录、性能监控、事务管理等。...

    java 动态代理实现AOP

    Java动态代理是Java语言提供的一个强大的特性,它允许开发者在运行时创建代理对象,以实现对目标对象的方法调用拦截。动态代理主要依赖于`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口。...

    Java反射与动态代理

    Java反射是Java编程语言中的一个强大特性,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。在Java中,反射机制的核心类包括`Class`、`Field`、`Method`和`Constructor`,它们分别代表类、...

    Java设计模式——代理设计模式(静态代理和动态代理)

    Java提供了一个内置的机制来实现动态代理,即`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口。 1. **定义接口**:与静态代理相同,我们依然需要一个业务接口`Service`。 2. **实现...

    java动态代理(2)

    Java动态代理机制是Java语言提供的一种强大的功能,它允许在运行时创建代理对象来实现指定的接口。这一机制使得我们可以在不修改已有代码的情况下,为已有接口增加额外的功能或者增强已有功能的行为。在Java中,动态...

    JAVA 反射机制与动态代理ppt

    Java 反射机制是Java语言中一种强大的工具,它允许程序在运行时探索和操作类、接口、对象的内部结构。反射机制的核心在于Java提供的`java.lang.reflect`包,其中包括了`Class`、`Field`、`Method`、`Constructor`和`...

    java动态代理机制分析及拓展

    Java 动态代理机制是Java语言提供的一种在运行时创建代理类和代理对象的机制,主要涉及`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口。动态代理通常用于实现AOP(面向切面编程)、事件...

    Java 动态代理详解(代理模式+静态代理+JDK动态代理+CGLIB动态代理)

    Java 动态代理是 Java 编程语言中的一种强大工具,广泛应用于 Spring AOP、Hibernate 数据查询、测试框架的后端 mock、RPC 远程调用、Java 注解对象获取、日志、用户鉴权、全局性异常处理、性能监控等领域。...

    java语言反射与动态代理学习笔记

    ### Java语言反射与动态代理深度解析 #### 一、Java反射机制详解 Java反射机制是Java编程语言的一个强大特性,允许程序在运行时检查和修改自身结构与行为。这一机制为开发人员提供了高度的灵活性,尤其是在框架...

    java动态代理类的实例

    Java动态代理是Java语言提供的一种高级特性,它允许我们在运行时创建一个代理对象来代替某个接口或类的对象,这个代理对象能够对方法调用进行拦截和处理。在Java中,动态代理主要通过`java.lang.reflect.Proxy`类和`...

    Java动态代理实现数据源连接池

    Java动态代理是Java语言提供的一种机制,它允许在运行时创建一个对象的代理,这个代理对象可以在调用实际方法之前和之后添加额外的功能。在Java中,动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang....

Global site tag (gtag.js) - Google Analytics