美文网首页
JAVA代理模式(静态代理、动态代理)

JAVA代理模式(静态代理、动态代理)

作者: 8090的大叔 | 来源:发表于2020-04-15 18:05 被阅读0次

作为学习Spring的一个基础,代理模式是了解的一个点。

代理模式:通过代理对象访问目标对象,并且可以对在不修改目标对象的情况下,在代理对象中增加额外的功能。

静态代理:通常只代理一个类(单一目标对象),使用前就已经知道被代理对象是什么,并且代理对象必须实现被代理对象相同的接口。(静态:类型是先预定好的,不可改变)

动态代理:代理类不需要实现接口,只有在运行时才知道代理的是什么对象。

JDK动态代理(目标对象实现了接口):实现InvocationHandler的invoke方法,通过Proxy.newProxyInstance得到代理对象。

CGLIB动态代理:可代理接口和类,不需要业务类继承接口,通过在内存中构建一个子类来进行代理。页脚子类代理。

静态代理:

/** 商品模块接口 */
interface IGoods{
    /* 购买商品 */
    void buyGoods();
}
/** 购买商品的实现 */
class GoodsImpl implements IGoods{
    @Override
    public void buyGoods() {
        System.out.println("购买了一个商品");
    }
}
/** 代理类 */
class GoodsProxy implements IGoods{
    private IGoods iGoods;
    //构造方法传入代理对象
    public GoodsProxy(IGoods iGoods){
        this.iGoods = iGoods;
    }
    @Override
    public void buyGoods() {
        System.out.println("选择了一个面包之后");
        this.iGoods.buyGoods();
        System.out.println("打包走人");
    }
}

public class AppStaticProxy {
    public static void main(String[] args) {
        IGoods iGoods = new GoodsImpl();
        GoodsProxy goodsProxy = new GoodsProxy(iGoods);
        goodsProxy.buyGoods();
    }
}

缺点:代理对象需要和目标对象实现一样的接口,如果目标太多,就会产生很多代理类。一旦接口增加,代理对象和目标对象都需要修改。使用动态代理方式,可以避免这类问题。

动态代理(JDK)
如果被代理对象实现了接口

package MyCode;

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

/** 商品业务接口 */
interface IGoods2{
    void buyGoods();
}
/** A购买商品的实现 */
class AGoodsImpl implements IGoods2{
    @Override
    public void buyGoods() {
        System.out.println("付钱购买");
    }
}
/** B购买商品的实现 */
class BGoodsImpl implements IGoods2{
    @Override
    public void buyGoods() {
        System.out.println("刷卡购买");
    }
}

/** 代理工厂 */
class ProxyFactory{
    Object target;
    public ProxyFactory(Object target){
        this.target = target;
    }
    /* 获取代理对象 */
    public Object getProxyInstance(){
        //实现 invoke 方法
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("选择商品种类");
                Object retVal = method.invoke(target,args);
                System.out.println("打包走人");
                return retVal;
            }
        };
        //返回代理对象
        Object object = Proxy.newProxyInstance(this.target.getClass().getClassLoader(), //目标类的ClassLoader
                this.target.getClass().getInterfaces(), //目标类的Interfaces
                invocationHandler);
        return object;
    }
}

public class AppJDKProxy {
    public static void main(String[] args) {
        IGoods2 AGoods = new AGoodsImpl(); //付钱
        IGoods2 BGoods = new BGoodsImpl(); //刷卡
        //通过代理获取两个目标对象
        IGoods2 proxyGoods = (IGoods2) new ProxyFactory(AGoods).getProxyInstance();
        proxyGoods.buyGoods();
        proxyGoods = (IGoods2) new ProxyFactory(BGoods).getProxyInstance();
        proxyGoods.buyGoods();
    }

}

动态代理(CGLIB)
代码以代理类的情况进行演示,第一步引入Cglib包

<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>
package MyCode;

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

import java.lang.reflect.Method;

/** A 商品购买 */
class AGoods{
    public void buyGoods() {
        System.out.println("付钱购买");
    }
}
/** B 商品购买实现 */
class BGoods{
    public void buyGoods() {
        System.out.println("刷卡购买");
    }
}


/** 代理工厂  实现MethodInterceptor*/
class CGProxyFactory implements MethodInterceptor {
    Object target;
    public CGProxyFactory(Object target){
        this.target = target;
    }
    //提供获取代理对象的方法
    public Object getProxyInstance(){
        Enhancer enhancer = new Enhancer();   //工具类
        enhancer.setSuperclass(this.target.getClass()); //设置父类(目标对象)
        enhancer.setCallback(this); //设置回调函数
        return enhancer.create();  //创建子类对象
    }
    //重写intercept方法
    @Override
    public Object intercept(Object obj, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("选择商品种类");
        Object retObj = method.invoke(this.target,objects);
        System.out.println("付钱购买");
        return retObj;
    }
}

public class AppCglib {
    public static void main(String[] args) {
        AGoods aGoods = new AGoods();
        BGoods bGoods = new BGoods();
        AGoods proxyAGoods = (AGoods)new CGProxyFactory(aGoods).getProxyInstance();
        proxyAGoods.buyGoods();
        BGoods proxyBGoods = (BGoods)new CGProxyFactory(bGoods).getProxyInstance();
        proxyBGoods.buyGoods();
    }
}

相关文章

网友评论

      本文标题:JAVA代理模式(静态代理、动态代理)

      本文链接:https://www.haomeiwen.com/subject/qwdcvhtx.html