趣谈AOP-静态代理原理

概念就不写了,直接写三种代理模式的实现方式:

静态代理

在程序运行前,代理类。class文件就已经生成了。是比较固定的实现,相对于动态生成代理来说这就是所谓的静态代理吧。我按自己的理解说的。

我们都知道,被静态代理的对象必须要实现一个接口,举个栗子。有些公司太严格,不许员工访问一些娱乐网站。怎么实现?当然是加权限,加这些娱乐网站的黑名单。就比如我在鹅厂,谁敢访问个支付宝试试。然后鹅厂就要给zhifubao加个网络连接的黑名单。我们简单看看用静态代理怎么实现。

首先,我们要定义一个上网的接口,让上网的人都访问这个接口:

public interface Internet {
    void connectTo(String hostName) throws Exception;
}

然后我们有个真实上网的对象去实现上网接口里规定的连接功能,当然就是被管理的对象咯。

public class RealInternet implements Internet {
    @Override
    public void connectTo(String hostName) throws Exception {
        System.out.println("小姐姐要访问 :" + hostName);
    }

}

那么被代理对象有了,我们怎么去实现对上网的管控呢?

首先,代理对象也要实现上网接口,其次,我们要让每个要上网的同学都必须把对象给我,当然此对象非彼对象哈。我要好好看看你到底有没有访问zhifubao,如果有不好意思,打屁股。

我们这样实现:

public class ProxyInternet implements Internet {
    /**
     * 不好意思,哥一夫当关
     */
    private Internet internet;

    /**
     * 来了啊,小姐姐
     *
     * @param internet 小姐姐本尊
     */
    public ProxyInternet(Internet internet) {
        this.internet = internet;
    }

    /**
     * 黑名单
     */
    private static List<String> bannedSites = new ArrayList<>();

    static {
        bannedSites.add("www.alibaba.com");
        bannedSites.add("www.alimama.com");
        bannedSites.add("www.alijiujiu.com");
        bannedSites.add("www.dingding.com");
        bannedSites.add("www.zhifubao.com");
    }

    /**
     * 这里是你做错事的惩罚
     *
     * @param hostName 小姐姐访问的网站
     */
    @Override
    public void connectTo(String hostName) throws Exception {
        if (bannedSites.contains(hostName)) {
            throw new Exception("访问" + hostName + "被我打了屁股!");
        }
        //绿色通道
        internet.connectTo(hostName);
    }
}

然后小伙伴不听劝告悄悄上网了,还访问了阿里mama

public class Client {
    public static void main(String[] args) {
        Internet internet = new ProxyInternet(new RealInternet());
        try {
            internet.connectTo("www.alimama.com");
        } catch (Exception e) {
            System.out.println("然后,小姐姐"+e.getMessage());
        }
    }
}

然后事情的结局是这样的:

当然也有听话的小伙伴

我们还可以用工厂模式来完全隐藏真实上网对象的逻辑实现:

public class Factory {
    public static Object newInstance(String name) {
        return new ProxyInternet(new RealInternet(name));
    }
}

 

public class RealInternet implements Internet {
    private String name;

    public RealInternet(String name) {
        this.name = name;
    }

    @Override
    public void connectTo(String hostName) throws Exception {
        System.out.println("小姐姐" +name+"要访问 :" + hostName);
    }

}

然后

public class Client {
    public static void main(String[] args) {
        Internet internet = (Internet) Factory.newInstance("小月亮");
        try {
            internet.connectTo("www.qq.com");
            System.out.println("小姐姐很乖,很听话!");
        } catch (Exception e) {
            System.out.println("然后,小姐姐"+e.getMessage());
        }
    }
}

我们看到Client里面没有任何 RealInternet 的信息,然后打印:

小姐姐小月亮要访问 :www.qq.com
小姐姐很乖,很听话!

 

总结

下面我们总结下优缺点:

优点

对被代理对象不做任何修改,甚至都看不到被代理对象的实现。只需要被代理对象交给代理对象代理就可以。我们称之为解耦。

缺点

代理类和被代理类都需要实现同一个接口,Override相同的方法,这样无形中增加了代码的冗余度

我们知道,接口中的方法实现类是必须要实现的,所以一旦我们增加或者修改接口中的方法的时候,实现类中的方法也要跟着修改。这也就增加了维护的难度

例子中ProxyInternet只能服务于Internet类型的对象。如果我们增加一种别的类型的对象,它就没办法代理了。要实现代理就必须对每一种对象都生成代理类才可以。所以如果需要代理的种类很多很多,静态代理就无法胜任了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值