Java代理模式

什么是代理模式:

代理模式是一种设计模式,简单说即是在不改变源码的情况下,实现对目标对象功能扩展

Java的代理模式有三种:

1.静态代理

/**
 * 目标对象实现了某一接口
 */
public class Singer implements ISinger {
    @Override
    public void sing() {
        System.out.println("唱一首歌");
    }
}
public interface ISinger {
    void sing();
}
public class SingerProxy implements ISinger {
    // 接收目标对象,以便调用sing方法
    private ISinger target;

    public SingerProxy(ISinger target) {
        this.target = target;
    }

    // 对目标对象的sing方法进行功能扩展
    @Override
    public void sing() {
        System.out.println("向观众问好");
        target.sing();
        System.out.println("谢谢大家");
    }
}
/**
 * 静态代理
 */
private void initProxy() {
    //目标对象
    ISinger target = new Singer();
    //代理对象
    ISinger proxy = new SingerProxy(target);
    //执行的是代理的方法
    proxy.sing();
}

总结:其实这里做的事情无非就是,创建一个代理类SingerProxy,继承了ISinger接口并实现了其中的方法。只不过这种实现特意包含了目标对象的方法,正是这种特征使得看起来像是“扩展”了目标对象的方法。假使代理对象中只是简单地对sing方法做了另一种实现而没有包含目标对象的方法,也就不能算作代理模式了。所以这里的包含是关键。

  缺点:这种实现方式很直观也很简单,但其缺点是代理对象必须提前写出,如果接口层发生了变化,代理对象的代码也要进行维护。如果能在运行时动态地写出代理对象,不但减少了一大批代理类的代码,也少了不断维护的烦恼,不过运行时的效率必定受到影响。这种方式就是接下来的动态代理。

2.动态代理(jdk)

/**
 * jdk动态代理
 */
private void initProxyTwo() {
    final Singer target = new Singer();
    ISinger proxy = (ISinger) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("动态代理向观众问好");
                    //执行目标对象方法
                    Object returnValue = method.invoke(target, args);
                    System.out.println("动态代理谢谢大家");
                    return returnValue;
                }
            });
    proxy.sing();
}

优点:由于java封装了newProxyInstance这个方法的实现细节,所以使用起来才能这么方便,具体的底层原理将会在下一小节说明。

缺点:可以看出静态代理和JDK代理有一个共同的缺点,就是目标对象必须实现一个或多个接口,加入没有,则可以使用Cglib代理。

3.动态代理(cglib)

前提条件:

  • 需要引入cglib的jar文件
  • 目标类不能为final
  • 目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法
public class Singer2 {
    public void sing() {
        System.out.println("singer2唱一首歌");
    }
}
public class ProxyFactory implements MethodInterceptor {
    // 维护目标对象
    private Object target;
    private Context context;
    public ProxyFactory(Object target,Context context) {
        this.target = target;
        this.context =context;
    }

    // 给目标对象创建一个代理对象
    public Object getProxyInstance() {
        //1.工具类
        Enhancer enhancer = new Enhancer(context);
        //2.设置父类
        enhancer.setSuperclass(target.getClass());
        //3.设置回调函数
        enhancer.setInterceptor(this);
        //4.创建子类(代理对象)
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Object[] objects, MethodProxy methodProxy) throws Exception {
        System.out.println("Cgclib向观众问好");
        Object result = methodProxy.invokeSuper(o, objects);
        System.out.println("Cgclib谢谢大家");
        return result;
    }
}
/**
 * cgclib动态代理
 */
private void initProxyThree() {
    //目标对象
    Singer2 target = new Singer2();
    //代理对象
    Singer2 proxy1 = (Singer2) new ProxyFactory(target,this).getProxyInstance();
    //执行代理对象的方法
    proxy1.sing();
}

cglib优点不用 写固定接口;

因为要添加cglib包 ,找了一圈才找到一个可以用的,晚上很多都不能用,所以贡献一个可以用的资源

https://download.csdn.net/my

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值