Java 设计模式之代理模式,Java 静态代理,Java 动态代理

Posted 蕃薯耀

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 设计模式之代理模式,Java 静态代理,Java 动态代理相关的知识,希望对你有一定的参考价值。

Java 设计模式之代理模式,Java 静态代理,Java 动态代理

 

================================

©Copyright 蕃薯耀 2021-06-21

https://www.cnblogs.com/fanshuyao/

 

一、Java 静态代理

1、定义接口

public interface IHouse {

    //卖房子
    void sale();
    
    //查看房子信息
    String house();
}

 

2、被代理的对象类(实际操作类)

public class HouseOwner implements IHouse {

    @Override
    public void sale() {
        System.out.println("。。。我将房子卖了");
    }

    @Override
    public String house() {
        return "该房子在深圳福田,售价:1.2亿";
    }

}

 

3、代理类

public class HouseProxy implements IHouse {

    //被代理的对象
    private HouseOwner houseOwner;
    
    public HouseProxy(HouseOwner houseOwner) {
        this.houseOwner = houseOwner;
    }

    @Override
    public void sale() {
        System.out.println("【中介】在卖房前做了什么");
        houseOwner.sale();
        System.out.println("【中介】在卖后收了多少佣金");
    }

    @Override
    public String house() {
        return houseOwner.house();
    }

}

 

4、测试

public class ProxyStatic {

    public static void main(String[] args) {
        
        HouseProxy houseProxy = new HouseProxy(new HouseOwner());
        houseProxy.sale();
        
        System.out.println("==============================");
        System.out.println(houseProxy.house());
        
    }
}

 

结果:

【中介】在卖房前做了什么
。。。我将房子卖了
【中介】在卖后收了多少佣金
==============================
该房子在深圳福田,售价:1.2亿

 

 

 

二、Java Jdk动态代理

1、动态代理类

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DynamicProxyFactoryJdk{
    
    private Object proxyTarget;

    public DynamicProxyFactoryJdk(Object proxyTarget) {
        this.proxyTarget = proxyTarget;
    }
    
    
    public Object getProxyInstance() {
        return Proxy.newProxyInstance(proxyTarget.getClass().getClassLoader(), proxyTarget.getClass().getInterfaces(), new InvocationHandler() {
            
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                
                System.out.println("jdk动态代理开始…");
                System.out.println("method.getName()="+ method.getName());
                Object returnObject = method.invoke(proxyTarget, args);//此处是proxyTarget对象,不是proxy参数
                System.out.println("jdk动态代理结束。");
                
                return returnObject;
            }
        });
    }
    
    

}

 

2、测试

public class ProxyDynamicJdk {

    public static void main(String[] args) {
        
//必须使用接口声明对象 IHouse proxyTarget
= new HouseOwner();
//必须使用接口声明对象 IHouse houseProxy
= (IHouse) new DynamicProxyFactoryJdk(proxyTarget).getProxyInstance(); System.out.println("+++++++++++++++++++++++++++++++"); System.out.println("houseProxy=" + houseProxy); System.out.println("houseProxy.getClass().getName()=" + houseProxy.getClass().getName()); System.out.println("=============================="); houseProxy.sale(); System.out.println("=============================="); System.out.println(houseProxy.house()); } }

 

结果:

+++++++++++++++++++++++++++++++
jdk动态代理开始…
method.getName()=toString
jdk动态代理结束。
houseProxy=com.lqy.springCloud.zzjava.designPattern.proxy.HouseOwner@6bc7c054
houseProxy.getClass().getName()=com.sun.proxy.$Proxy0
==============================
jdk动态代理开始…
method.getName()=sale
。。。我将房子卖了
jdk动态代理结束。
==============================
jdk动态代理开始…
method.getName()=house
jdk动态代理结束。
该房子在深圳福田,售价:1.2亿

 

 

三、Java cglib 动态代理

1、动态代理类(需要需要引入cglib相关包)

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

 

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/**
 * 需要引入cglib包
 *
 */
public class DynamicProxyFactoryCglib implements MethodInterceptor{
    
    private Object proxyTarget;

    public DynamicProxyFactoryCglib(Object proxyTarget) {
        this.proxyTarget = proxyTarget;
    }
    
    
    public Object getProxyInstance() {
        return Enhancer.create(proxyTarget.getClass(), this);
    }


    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        
        System.out.println("cglib动态代理开始…");
        System.out.println("method.getName()="+ method.getName());
        Object returnObject = method.invoke(proxyTarget, args);//此处是proxyTarget对象,不是obj参数
        System.out.println("cglib动态代理结束。");
        
        return returnObject;
    }
    
    

}

 

 

2、测试

public class ProxyDynamicCglib {

    public static void main(String[] args) {
        
        HouseOwner houseOwner = (HouseOwner) new DynamicProxyFactoryCglib(new HouseOwner()).getProxyInstance();
        
        System.out.println("+++++++++++++++++++++++++++++++");
        System.out.println("houseOwner=" + houseOwner);
        System.out.println("houseOwner.getClass().getName()=" + houseOwner.getClass().getName());
        
        System.out.println("==============================");
        
        houseOwner.sale();
        
        System.out.println("==============================");
        System.out.println(houseOwner.house());
        
        
    }
}

 

结果:

+++++++++++++++++++++++++++++++
cglib动态代理开始…
method.getName()=toString
cglib动态代理结束。
houseOwner=com.lqy.springCloud.zzjava.designPattern.proxy.HouseOwner@6842775d
houseOwner.getClass().getName()=com.lqy.springCloud.zzjava.designPattern.proxy.HouseOwner$$EnhancerByCGLIB$$8067e885
==============================
cglib动态代理开始…
method.getName()=sale
。。。我将房子卖了
cglib动态代理结束。
==============================
cglib动态代理开始…
method.getName()=house
cglib动态代理结束。
该房子在深圳福田,售价:1.2亿

 

 

四、总结

 

静态代理:

实现较简单,只要声明一个代理对象对目标对象进行包装,即可实现代理功能,但静态代理只能为一个目标对象服务,如果目标对象过多,则会产生很多代理类。

静态代理在编译时产生class字节码文件,可以直接使用,效率高。


JDK 动态代理:

需要目标对象实现业务接口(目标类和代理类必须实现相同的接口),代理类只需实现InvocationHandler接口。
动态代理必须实现InvocationHandler接口,通过反射代理方法,比较消耗系统性能,但可以减少代理类的数量,使用更灵活。

 

cglib 动态代理:

cglib (Code Generation Library )是一个第三方代码生成类库,运行时在内存中动态生成一个子类对象从而实现对目标对象功能的扩展。

使用cglib需要引入cglib的jar包
cglib代理无需实现接口,通过生成类字节码实现代理,比反射稍快,不存在性能问题,但cglib会继承目标对象,需要重写方法,所以目标对象不能为final类。

使用cglib代理的对象则无需实现接口,达到代理类无侵入。

 

 

================================

©Copyright 蕃薯耀 2021-06-21

https://www.cnblogs.com/fanshuyao/

以上是关于Java 设计模式之代理模式,Java 静态代理,Java 动态代理的主要内容,如果未能解决你的问题,请参考以下文章

java代理模式之静态代理

设计模式之代理模式详解(java)

设计模式之代理模式详解(java)

Java设计模式-代理模式之动态代理(附源代码分析)

代理模式之静态代理

Spring之代理模式