面试官问 Spring AOP 中两种代理模式的区别,我懵逼了

基本介绍代理模式是一种结构性设计模式 。为对象提供一个替身 , 以控制对这个对象的访问 。即通过代理对象访问目标对象 , 并允许在将请求提交给对象前后进行一些处理 。
被代理的对象可以是远程对象、创建开销大的对象或需要安全控制的对象 。
代理模式主要有三种不同的形式:

  • 静态代理:由程序员创建代理类或特定工具自动生成源代码再对其编译 。在程序运行前代理类的 .class 文件就已经存在了
  • 动态代理(JDK 代理、接口代理):在程序运行时运用反射机制动态创建而成 , 动态就是在程序运行时生成的 , 而不是编译时 。
  • cglib 代理(可以在内存动态的创建对象 , 而不是实现接口 , 属于动态代理的范畴)
问题为什么要控制对于某个对象的访问呢?举个例子:有这样一个消耗大量系统资源的巨型对象 ,  你只是偶尔需要使用它 ,  并非总是需要 。
面试官问 Spring AOP 中两种代理模式的区别,我懵逼了

文章插图
 
你可以实现延迟初始化:在实际有需要时再创建该对象 。对象的所有客户端都要执行延迟初始代码 。不幸的是 ,  这很可能会带来很多重复代码 。
在理想情况下 ,  我们希望将代码直接放入对象的类中 ,  但这并非总是能实现:比如类可能是第三方封闭库的一部分 。
解决方案代理模式建议新建一个与原服务对象接口相同的代理类 ,  然后更新应用以将代理对象传递给所有原始对象客户端 。代理类接收到客户端请求后会创建实际的服务对象 ,  并将所有工作委派给它 。
面试官问 Spring AOP 中两种代理模式的区别,我懵逼了

文章插图
 
代理将自己伪装成数据库对象 ,  可在客户端或实际数据库对象不知情的情况下处理延迟初始化和缓存查询结果的工作 。
这有什么好处呢?如果需要在类的主要业务逻辑前后执行一些工作 ,  你无需修改类就能完成这项工作 。由于代理实现的接口与原类相同 ,  因此你可将其传递给任何一个使用实际服务对象的客户端 。
代理模式结构
面试官问 Spring AOP 中两种代理模式的区别,我懵逼了

文章插图
 
  • 1.服务接口 (Service Interface) 声明了服务接口 。代理必须遵循该接口才能伪装成服务对象 。
  • 服务 (Service) 类提供了一些实用的业务逻辑 。
  • 代理 (Proxy) 类包含一个指向服务对象的引用成员变量 。代理完成其任务 (例如延迟初始化、 记录日志、 访问控制和缓存等) 后会将请求传递给服务对象 。通常情况下 ,  代理会对其服务对象的整个生命周期进行管理 。
  • 客户端 (Client) 能通过同一接口与服务或代理进行交互 ,  所以你可在一切需要服务对象的代码中使用代理 。
打游戏有代练、买卖房子有中介代理、再比如一般公司投互联网广告也可以找代理公司 , 这里的代练、中介、广告代理公司扮演的角色都是代理 。
这里举个更接近程序员的例子 , 比如有些变态的公司不允许在公司刷微博 , 看视频 , 可以通过一层代理来限制我们访问这些网站 。
废话不多说 , 先来个静态代理 。
静态代理1、定义网络接口
public interface Internet {    void connectTo(String serverHost) throws Exception;}2、真正的网络连接
public class RealInternet implements Internet{    @Override    public void connectTo(String serverHost) throws Exception {        System.out.println("Connecting to "+ serverHost);    }}3、公司的网络代理
public class ProxyInternet implements Internet {    //目标对象 , 通过接口聚合    private Internet internet;    // 通过构造方法传入目标对象    public ProxyInternet(Internet internet){        this.internet = internet;    }    //网络黑名单    private static List<String> bannedSites;    static    {        bannedSites = new ArrayList<String>();        bannedSites.add("bilibili.com");        bannedSites.add("youtube.com");        bannedSites.add("weibo.com");        bannedSites.add("qq.com");    }    @Override    public void connectTo(String serverhost) throws Exception {        // 添加限制功能        if(bannedSites.contains(serverhost.toLowerCase()))        {            throw new Exception("Access Denied:"+serverhost);        }        internet.connectTo(serverhost);    }}


推荐阅读