java中的三种代理模式

JDK 动态代理

这里记录一下自己对代理的理解,重点为JDK动态代理。首先要明确一件事情,代理这个词既可以是名字也可以是动词。要注意区分。名词时候,叫做代理商也许会更好一些。

代理的目的

为什么需要代理,我觉得更多的时候是为了实现对某一个切面的编程。比如,我们有一个动物类,在开发中,我们发现需要给动物类的子类进行一次扩展,这里我们可以使用继承。但是,如果是同时很多子类都需要这个方法,又不是所有的子类都需要。我们怎么做?这里我们就可以使用代理来实现扩展。对于需要扩展的子类,我们并不直接new出来,而是通过一个代理类生成,代理类中在原有的基础上进行了扩展,增加了新的方法。就像我们现在手里有很多树木,各种种类的树木。其中有很多珍贵的红木。这玩意当然自己出售放心。还有很多松木,杨木。这种便宜的东西出售时候我们就不用太在意了,找个委托商,我只要这些木头给我钱,至于你想怎么销售,卖给谁,买家希望做成什么样子。我都不再关心了。而这里的委托商,就是一个代理。我们把木头给他,至于做成桌子,椅子都无所谓了。这就是代理。

JAVA中代理的种类

在java中代理有三种。分别为静态代理,JDK动态代理,和CgLib代理。

静态代理

静态代理比较简单,就是通过建立一个代理类(与被代理的对象使用相同的接口),然后在代理类里通过组合的形式,把需要被代理的对象传入,重写的方法中调用被代理对象的方法即可实现。

静态代理demo

subject:

/**
 * @author sunyan
 * @description
 */
public interface Subject {
    /**
     *需要增强的方法
     */
    void doSomeThing();
}

需要被代理的类
RealSubject

/**
 * @author sunyan
 * @description
 */
public class RealSubject implements Subject{
    @Override
    public void doSomeThing() {
        System.out.println("我是需要被代理的对象");
    }
}

代理商

/**
 * @author sunyan
 * @description
 */
public class Proxyer implements Subject{
    private Subject subject;

    public Proxyer(Subject subject) {
        this.subject = subject;
    }

    @Override
    public void doSomeThing() {
        System.out.println("我代理了它,开始执行");
        subject.doSomeThing();
        System.out.println("代理处理完成");
    }
}

到这里静态代理就结束了,只要调用Proxyer产生的对象里的doSomeThing()就可以对原对象方法进行增强。

JDK动态代理

对于上面的方法存在一个问题,如果买家说我需要一把铁做的椅子(卖木头的赚钱赚多了,行业扩展了),可我们接口却是木头,这就尴尬了,你不能说我只有木头的接口,没法生存椅子。怎么办?最好的方法就是把接口做成灵活的。这样就可以代理做任何材料的椅子了。在java中我们可以通过反射来实现这个功能。
我们只需要下面三个步骤就可以完成jdk动态代理
1.定义一个接口(当然这个接口无所谓啦,定义哪个都行)
2.定义一个代理商,这个代理商就很特别了,他需要实现InvocationHandler接口,并重写里面的invoke。这个接口里只存在一个方法。就是invoke。

    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;

3.第三步,我们要在代理商里(其他地方也行)调用Proxy.newProxyInstance()方法;通过读源码的注释可以发现

 public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

@return a proxy instance with the specified invocation handler of a
proxy class that is defined by the specified class loader and that implements the specified interfaces
,这里会返回一个代理对象,它使用loader加载器,实现一些特殊接口(特殊接口就是我们需要被代理对象的接口)
可能你会觉得很奇怪,在代理中没有调用invoke方法就可以实现增强的方法了。其实。。。。。我也不太懂,但是根据我的直觉,应该是我们调用方法的时候,那个.就是对invoke的调用。
具体代码如下:

Subject接口:

public interface Subject {
    /**
     *
     */
    void doSomeThing();
}```
需要被代理的对象的类:

```java
public class RealSubject implements Subject {
    @Override
    public void doSomeThing() {
        System.out.println("需要被代理的事务");
    }
}

代理商

/**
 * @author sunyan
 * @description
 */
public class ProxyFactory implements InvocationHandler {
    private Object target;

    public ProxyFactory(Object target) {
        this.target = target;
    }

    public <T> T getInstance(){
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("前置增强");
        method.invoke(target);
        return null;
    }
}```
#### cglib动态代理
这个动态代理和上面的不太一样,它是基于父类继承,通过过滤器实现的,emm,具体的实现过程还没有好好观摩,等观摩好了再继续
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值