java动态代理实现Proxy和InvocationHandler cglib

简介: 概念:静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。 动态代理:在程序运行时,运用反射机制动态创建而成。 JDK的动态代理用起来非常简单,当它有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的继承的类,该怎么办?现在我们可以使用CGLIB包。JDK动态代理实现import ja




概念:

静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。 
动态代理:在程序运行时,运用反射机制动态创建而成。


JDK的动态代理用起来非常简单,当它有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的继承的类,该怎么办?现在我们可以使用CGLIB包。



JDK动态代理实现

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;


public class ProxyTest {
    static StringBuilder sBuilder=new StringBuilder();
    public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        
        //代理类字节码
Class clazzProxy1=    Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
//代理类构造方法列表,没有无参构造方法
System.out.println("...........begin constructors list............");
    Constructor[] constructors= clazzProxy1.getConstructors();
     for(Constructor constructor:constructors){
         StringBuilder sBuilder=new StringBuilder();
        sBuilder.append(constructor.getName()).append("(");
        Class[] clazzparams =constructor.getParameterTypes();
    
        for(Class clazzparam:clazzparams){
            
            sBuilder.append(clazzparam.getName()).append(",");
            
        }
        
        if(clazzparams.length!=0){
            
            sBuilder.deleteCharAt(sBuilder.length()-1);
        }
        sBuilder.append(")");
        System.out.println( sBuilder.toString());
     }
    
    //代理类方法列表
    System.out.println("...........begin methods list............");
     
    Method[] methods= clazzProxy1.getMethods();
     for(Method method:methods){
         StringBuilder sBuilder=new StringBuilder();
        sBuilder.append(method.getName()).append("(");
        Class[] clazzparams =method.getParameterTypes();
    
        for(Class clazzparam:clazzparams){
            
            sBuilder.append(clazzparam.getName()).append(",");
            
        }
        
        if(clazzparams.length!=0){
            
            sBuilder.deleteCharAt(sBuilder.length()-1);
        }
        sBuilder.append(")");
        System.out.println( sBuilder.toString());
     }
     
     //通过字节码创建代理类的实例,不能用newInstance(),构造方法传入InvocationHandler
     System.out.println("...........begin create instance object............");
    
        Constructor constructor=clazzProxy1.getConstructor(InvocationHandler.class);
        
    Collection proxy1=    (Collection) constructor.newInstance(new InvocationHandler(){

            @Override
            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                
                return null;
            }
            
        });
        
    System.out.println(proxy1);
    proxy1.clear();//无返回值的方法成功

    //一步到位创建代理类实例
    Collection proxy2=(Collection) Proxy.newProxyInstance(Collection.class.getClassLoader(),new Class[]{Collection.class}, new InvocationHandler(){
        ArrayList target=new ArrayList<>();//被代理对象,目标对象
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            
            long begintime=System.currentTimeMillis();
            Object retVal=method.invoke(target, args);
            long endtime=System.currentTimeMillis();
            System.out.println(method.getName()+" running time is " +(endtime-begintime));
            return retVal;
        }
        
    });
    
    proxy2.add("lhm");
    proxy2.add("zxx");
    proxy2.add("bxd");
    System.out.println(proxy2.size());
    System.out.println(proxy2.getClass().getName());
    }
        
    
    
    
}


CGLIB(CODE GENERLIZE LIBRARY)代理是针对类实现代理,

主要是对指定的类生成一个子类覆盖其中的所有方法,所以该类或方法不能声明称final的。


spring中Aspect动态代理设置

Spring提供了两种方式来生成代理对象: JDKProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。

默认的策略是如果目标类是接口,则使用JDK动态代理技术,如果目标对象没有实现接口,则默认会采用CGLIB代理。

如果目标对象实现了接口,可以强制使用CGLIB实现代理(添加CGLIB库,并在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)。


本文出自 “点滴积累” 博客,请务必保留此出处http://tianxingzhe.blog.51cto.com/3390077/1719600

目录
相关文章
|
26天前
|
Java
JAVA 静态代理 & 动态代理
【11月更文挑战第14天】静态代理是一种简单的代理模式实现,其中代理类和被代理类的关系在编译时已确定。代理类实现与被代理类相同的接口,并持有被代理类的实例,通过调用其方法实现功能增强。优点包括代码结构清晰,易于理解和实现;缺点是对于多个被代理类,需为每个类编写相应的代理类,导致代码量大增,维护成本高。动态代理则在运行时动态生成代理类,更加灵活,减少了代码冗余,但可能引入性能损耗和兼容性问题。
|
2月前
|
设计模式 Java API
[Java]静态代理与动态代理(基于JDK1.8)
本文介绍了代理模式及其分类,包括静态代理和动态代理。静态代理分为面向接口和面向继承两种形式,分别通过手动创建代理类实现;动态代理则利用反射技术,在运行时动态创建代理对象,分为JDK动态代理和Cglib动态代理。文中通过具体代码示例详细讲解了各种代理模式的实现方式和应用场景。
31 0
[Java]静态代理与动态代理(基于JDK1.8)
|
2月前
|
Java
深入理解Java动态代理
深入理解Java动态代理
91 1
|
2月前
|
Java
Java代码解释静态代理和动态代理的区别
### 静态代理与动态代理简介 **静态代理**:代理类在编译时已确定,目标对象和代理对象都实现同一接口。代理类包含对目标对象的引用,并在调用方法时添加额外操作。 **动态代理**:利用Java反射机制在运行时生成代理类,更加灵活。通过`Proxy`类和`InvocationHandler`接口实现,无需提前知道接口的具体实现细节。 示例代码展示了两种代理方式的实现,静态代理需要手动创建代理对象,而动态代理通过反射机制自动创建。
|
2月前
|
设计模式 缓存 Java
从源码学习Java动态代理|8月更文挑战
从源码学习Java动态代理|8月更文挑战
|
4月前
|
开发者 C# 容器
【独家揭秘】当WPF邂逅DirectX:看这两个技术如何联手打造令人惊艳的高性能图形渲染体验,从环境搭建到代码实践,一步步教你成为图形编程高手
【8月更文挑战第31天】本文通过代码示例详细介绍了如何在WPF应用中集成DirectX以实现高性能图形渲染。首先创建WPF项目并使用SharpDX作为桥梁,然后在XAML中定义承载DirectX内容的容器。接着,通过C#代码初始化DirectX环境,设置渲染逻辑,并在WPF窗口中绘制图形。此方法适用于从简单2D到复杂3D场景的各种图形处理需求,为WPF开发者提供了高性能图形渲染的技术支持和实践指导。
277 0
|
4月前
|
设计模式 Java C++
揭秘!JDK动态代理VS CGLIB:一场关于Java代理界的‘宫心计’,你站哪队?
【8月更文挑战第24天】Java 动态代理是一种设计模式,允许在不改动原类的基础上通过代理类扩展功能。主要实现方式包括 JDK 动态代理和 CGLIB。前者基于接口,利用反射机制在运行时创建代理类;后者采用继承方式并通过字节码技术生成子类实现类的代理。两者在实现机制、性能及适用场景上有明显差异。JDK 动态代理适用于有接口的场景,而 CGLIB 更适合代理未实现接口的类,尽管性能更优但存在一些限制。开发者可根据需求选择合适的代理方式。
202 0
|
Java Spring API
|
3天前
|
安全 Java API
java如何请求接口然后终止某个线程
通过本文的介绍,您应该能够理解如何在Java中请求接口并根据返回结果终止某个线程。合理使用标志位或 `interrupt`方法可以确保线程的安全终止,而处理好网络请求中的各种异常情况,可以提高程序的稳定性和可靠性。
28 6