YAZONG 我的开源

设计模式(四)结构型模式(对象结构型模式)代理模式-PROXY

 
0 评论0 浏览

2、4 代理模式

定义

为其他对象提供一种代理以控制对这个对象的访问。

案例

案例情景 1-1

图形结构

image.png

代码示例

public class Client1 {
    public static void main(String[] args) {
        IGamePlayer gamePlayer = new GamePlayer("测试用户");
        gamePlayer.login("testuser","123456");
        gamePlayer.killBoss();
        gamePlayer.upgrade();
    }
}
interface IGamePlayer {
    //登录游戏
    void login(String user,String password);
    //杀怪
    void killBoss();
    //升级
    void upgrade();
}
class GamePlayer implements IGamePlayer{

    private String name;

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

    @Override
    public void login(String user, String password) {
        System.out.println("登录用户名:" + user + ",密码:" + password + ".");
    }

    @Override
    public void killBoss() {
        System.out.println(this.name + "在打怪.");
    }

    @Override
    public void upgrade() {
        System.out.println(this.name + "又升级了!");
    }
}

案例情景 1-2 优化

图形结构

image.png

代码示例

public class Client2 {
    public static void main(String[] args) {
        IGamePlayer gamePlayer = new GamePlayer("测试用户");
        IGamePlayer proxy = new GamePlayerProxy(gamePlayer);
        proxy.login("usertest","123456");
        proxy.killBoss();
        proxy.upgrade();
    }
}

interface IGamePlayer {
    //登录游戏
    void login(String user,String password);
    //杀怪
    void killBoss();
    //升级
    void upgrade();
}
class GamePlayer implements IGamePlayer{

    private String name;

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

    @Override
    public void login(String user, String password) {
        System.out.println("登录用户名:" + user + ",密码:" + password + ".");
    }

    @Override
    public void killBoss() {
        System.out.println(this.name + "在打怪.");
    }

    @Override
    public void upgrade() {
        System.out.println(this.name + "又升级了!");
    }
}
class GamePlayerProxy implements IGamePlayer{

    private IGamePlayer gamePlayer;

    public GamePlayerProxy(IGamePlayer gamePlayer) {
        this.gamePlayer = gamePlayer;
    }

    @Override
    public void login(String user, String password) {
        this.gamePlayer.login(user,password);
    }

    @Override
    public void killBoss() {
        this.gamePlayer.killBoss();
    }

    @Override
    public void upgrade() {
        this.gamePlayer.upgrade();
    }
}

案例 2 代理通用案例

图形结构

image.png

代码示例

public class Client3 {
}

/**
 * 抽象主题类
 */
interface Subject{
    void request();
}

/**
 * 真实主题类
 */
class RealSubject implements Subject{
    @Override
    public void request() {
        //业务逻辑处理
    }
}

/**
 * 代理类
 */
class Proxy implements Subject{

    //要代理哪个实现类
    private Subject subject = null;
    //默认被代理类
    public Proxy() {
        this.subject = new Proxy();
    }
    //通过构造函数传递代理者
    //一个代理类可以代理多个被委托者或被代理类,因此一个代理类具体代理哪个真实主题角色,是由场景类决定的。
    //在通常情况下,一个接口只需要一个代理类就可以了,具体代理哪个实现类由高层模块来决定
    //也就是在代理类的构造函数中传递被代理者
    public Proxy(Object ...objects) {
    }
    //实现接口中定义的方法
    @Override
    public void request() {
        this.before();
        this.subject.request();
        this.after();
    }
    //预处理
    private void before(){
    }
    //善后处理
    private void after(){
    }
}

代理模式的应用

优点

1.职责清晰

真实的角色就是实现实际的业务逻辑,不用关系其他非本职责的事物,通过后期的代理完成一件事物,附带的结果就是编程简洁清晰。

2.高扩展性

具体主题角色是随时都会发生变化的,只要它实现了接口,甭管它如何变化,都逃不脱接口,那么我们的代理类完全就可以在不做任何修改的情况下使用。

3.智能化

比如动态代理、Struts 如何把表单元素映射到对象上的。

使用场景

为什么要使用代理?“其实是自己不想参与中间的是是非非”。
比如 SpringAOP 就是非常典型的动态代理。

1、远程代理,也就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实。
(比如 webservice。)

2、虚拟代理,是根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象。
(这样可以达到性能的最优化,比如说打开一个很大的 HTML 网页,里面很多文字和图片,此时看到的是所有的文字,但是图片却是一张一张地下载后才能看到,那些未打开的图片框,就是通过虚拟代理来替代了真实的图片,此时代理存储了真实图片的路径和尺寸。)

3、安全代理,用来控制真实对象访问时的权限。
(一般用于对象应该有不同的访问权限的时候。)

4、智能指引,是指当时调用真实对象时,代理处理另外一些事。
(如计算真实对象的引用次数,这样当该对象没有引用时,可以自动释放它;或当第一次引用一个持久化对象时,将它装入内存;或在访问一个实际对象前,检查是否已经锁定它,以确保其他对象不能改变它。它们都是通过代理在访问一个对象时附加一些内务处理。)

综上所述,代理模式其实就是在访问对象时引入一定程度的间接性,因为这种间接性,可以附加多种用途。代理模式就是真实对象的代表。

代理模式的扩展

普通代理

定义

客户端只能访问代理角色,而不能访问真实角色。

案例

图形结构

image.png

代码示例
public class Client4 {
    public static void main(String[] args) {
        IGamePlayer gamePlayerProxy = new GamePlayerProxy("测试用户");
        gamePlayerProxy.login("testuser","testpassword");
        gamePlayerProxy.killBoss();
        gamePlayerProxy.upgrade();
    }
}
interface IGamePlayer {
    //登录游戏
    void login(String user,String password);
    //杀怪
    void killBoss();
    //升级
    void upgrade();
}
class GamePlayer implements IGamePlayer{

    private String name = "";

    public GamePlayer(IGamePlayer gamePlayer,String name) throws Exception{

        if(gamePlayer == null){
            throw new Exception("不能创建真实角色!");
        }else{
            this.name = name;
        }

    }

    @Override
    public void login(String user, String password) {
        System.out.println("登录名为:" + user + "的用户:" + this.name + "登录成功!");
    }

    @Override
    public void killBoss() {
        System.out.println(this.name + "在打怪.");
    }

    @Override
    public void upgrade() {
        System.out.println(this.name + "又升了一级!");
    }
}

class GamePlayerProxy implements IGamePlayer{

    private IGamePlayer gamePlayer = null;

    public GamePlayerProxy(String name) {
        try {
            //这里要实例化真实的类有点不太理解
            this.gamePlayer = new GamePlayer(this,name);

        }catch (Exception e){
            //TODO
            e.printStackTrace();
        }
    }

    @Override
    public void login(String user, String password) {
        this.gamePlayer.login(user,password);
    }

    @Override
    public void killBoss() {
        this.gamePlayer.killBoss();
    }

    @Override
    public void upgrade() {
        this.gamePlayer.upgrade();
    }
}

描述

在该模式下,调用者只知代理而不用知道真实的角色是谁,屏蔽了真实角色的变更对高层模块的影响,该模式非常适合对扩展性要求较高的场合。在实际的项目中,一般都是通过约定来禁止 new 一个真实的角色。

注意:普通代理模式的约束问题尽量通过团队内的编程规范类约束,因为每一个主题类是可被重用的和可维护的,使用技术约束的方式对系统维护是一种非常不利的因素。

强制代理

定义

必须通过真实角色查找到代理角色(不允许直接访问真实角色),否则不能访问。甭管是通过代理类还是通过直接 new 一个主题角色类,都不能访问,只有通过真实角色指定的代理类才可以访问,也就是说由真实角色管理代理角色,可以不用知道代理存在,但是你的所作所为还是需要代理为你提供。

案例

图形结构

image.png

代理示例
public class Client5 {

    public static void main(String[] args) {

        //直接访问真实角色
        //必须通过代理来访问,不能直接访问它
        System.out.println("---------直接访问真实角色begin---------");
        IGamePlayer gamePlayer1 = new GamePlayer("测试用户");
        gamePlayer1.login("testuser","testpassword");
        gamePlayer1.killBoss();
        gamePlayer1.upgrade();
        System.out.println("---------直接访问真实角色end---------");

        //直接访问代理类
        //不能访问是由于不是真实角色指定的对象,这个代理对象是自己new出来的,当然真实对象不认了
        System.out.println("---------直接访问代理类begin---------");
        IGamePlayer gamePlayer2 = new GamePlayer("测试用户");
        IGamePlayer gamePlayerProxy2 = new GamePlayerProxy(gamePlayer2);
        gamePlayerProxy2.login("testuser","testpassword");
        gamePlayerProxy2.killBoss();
        gamePlayerProxy2.upgrade();
        System.out.println("---------直接访问代理类end---------");

        //强制代理的场景类
        //强制代理的概念就是要从真实角色查找到代理角色,不允许直接访问真实角色。
        //高层模块只要调用getProxy就可以访问真实角色的所有访问,
        //它根本就不需要产生一个代理出来,代理的管理已经由真实角色自己完成。
        System.out.println("---------强制代理的场景类begin---------");
        IGamePlayer gamePlayer3 = new GamePlayer("测试用户");
        //获得指定的代理
        IGamePlayer gamePlayerProxy3 = gamePlayer3.getProxy();
        gamePlayerProxy3.login("testuser","testpassword");
        gamePlayerProxy3.killBoss();
        gamePlayerProxy3.upgrade();
        System.out.println("---------强制代理的场景类end---------");

    }

}
interface IGamePlayer{
    //登录游戏
    void login(String user,String password);
    //杀怪
    void killBoss();
    //升级
    void upgrade();
    //每个人都可以找到自己的代理
    IGamePlayer getProxy();
}
class GamePlayer implements IGamePlayer{

    private String name;
    private IGamePlayer proxy;

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

    @Override
    public IGamePlayer getProxy() {
        //找到自己的代理
        this.proxy = new GamePlayerProxy(this);
        return this.proxy;
    }

    private boolean isProxy(){
        if(this.proxy == null){
            return Boolean.FALSE;
        }else{
            return Boolean.TRUE;
        }
    }
    
    @Override
    public void login(String user, String password) {
        if(this.isProxy()){
            System.out.println("登录名为:" + user + "的用户:" + this.name + "登录成功!");
        }else{
            System.out.println("login-请使用指定的代理访问!");
        }
    }

    @Override
    public void killBoss() {
        if(this.isProxy()){
            System.out.println(this.name + "在打怪.");
        }else{
            System.out.println("killBoss-请使用指定的代理访问!");
        }
    }

    @Override
    public void upgrade() {
        if(this.isProxy()){
            System.out.println(this.name + "又升了一级!");
        }else{
            System.out.println("upgrade-请使用指定的代理访问!");
        }
    }

}
class GamePlayerProxy implements IGamePlayer{

    private IGamePlayer gamePlayer;

    public GamePlayerProxy(IGamePlayer gamePlayer) {
        this.gamePlayer = gamePlayer;
    }

    @Override
    public void login(String user, String password) {
        this.gamePlayer.login(user,password);
    }

    @Override
    public void killBoss() {
        this.gamePlayer.killBoss();
    }

    @Override
    public void upgrade() {
        this.gamePlayer.upgrade();
    }

    @Override
    public IGamePlayer getProxy() {
        return this;
    }
}

代理是有个性的

定义

一个类可以实现多个接口,完成不同任务的整合。也就是说代理类不仅仅可以实现主题接口,也可以实现其他接口完成不同的任务,而且代理的目的是在目标对象方法的基础上做增强,这种增强的本质通常就是对目标对象的方法进行拦截和过滤。

代理类不仅仅是可以有自己的运算方法,通常的情况下,代理的职责并不一定单一,它可以组合其他的真实角色,也可以实现自己的职责,比如下述案例中的计算费用(count()方法)。

代理类可以为真实角色预处理消息、过滤消息、消息转发、事后处理消息等功能。当然一个代理类,可以代理多个真实角色,并且真实角色之间可以有耦合关系,可以自行扩展。

案例

图形结构

image.png

代码示例
public class Client6 {
    public static void main(String[] args) {

        IGamePlayer gamePlayer = new GamePlayer("测试用户");
        //获得指定的代理
        IGamePlayer gamePlayerProxy = gamePlayer.getProxy();
        gamePlayerProxy.login("testuser","testpassword");
        gamePlayerProxy.killBoss();
        gamePlayerProxy.upgrade();

    }

}
interface IGamePlayer{
    //登录游戏
    void login(String user,String password);
    //杀怪
    void killBoss();
    //升级
    void upgrade();
    //每个人都可以找到自己的代理
    IGamePlayer getProxy();
}
interface IProxy{
    void count();
}
class GamePlayer implements IGamePlayer{

    private String name;
    private IGamePlayer proxy;

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

    @Override
    public IGamePlayer getProxy() {
        //找到自己的代理
        this.proxy = new GamePlayerProxy(this);
        return this.proxy;
    }

    private boolean isProxy(){
        if(this.proxy == null){
            return Boolean.FALSE;
        }else{
            return Boolean.TRUE;
        }
    }

    @Override
    public void login(String user, String password) {
        if(this.isProxy()){
            System.out.println("登录名为:" + user + "的用户:" + this.name + "登录成功!");
        }else{
            System.out.println("login-请使用指定的代理访问!");
        }
    }

    @Override
    public void killBoss() {
        if(this.isProxy()){
            System.out.println(this.name + "在打怪.");
        }else{
            System.out.println("killBoss-请使用指定的代理访问!");
        }
    }

    @Override
    public void upgrade() {
        if(this.isProxy()){
            System.out.println(this.name + "又升了一级!");
        }else{
            System.out.println("upgrade-请使用指定的代理访问!");
        }
    }

}
class GamePlayerProxy implements IGamePlayer,IProxy{

    private IGamePlayer gamePlayer;

    public GamePlayerProxy(IGamePlayer gamePlayer) {
        this.gamePlayer = gamePlayer;
    }

    @Override
    public void login(String user, String password) {
        this.gamePlayer.login(user,password);
    }

    @Override
    public void killBoss() {
        this.gamePlayer.killBoss();
    }

    @Override
    public void upgrade() {
        this.gamePlayer.upgrade();
        this.count();
    }

    @Override
    public IGamePlayer getProxy() {
        return this;
    }

    @Override
    public void count() {
        System.out.println("升级总费用是150元.");
    }
}

动态代理(重点)

定义

动态代理是在实现阶段不用关心代理谁,而在运行阶段不指定代理哪一个对象。相对来说,自己写代理类的方式是静态代理。

动态代理是根据被代理的接口生成所有的方法,也就是说给定一个接口,动态代理会宣称“我已经实现该接口下的所有方法了”。

案例

案例 1

图形结构

image.png

代码示例 1-1
public class Client7 {
    public static void main(String[] args) {
        IGamePlayer player = new GamePlayer("测试用户");
        InvocationHandler handler = new GamePlayerIH(player);
        ClassLoader cl = player.getClass().getClassLoader();
        //动态产生一个代理者
        IGamePlayer proxy = (IGamePlayer) Proxy.newProxyInstance(cl,new Class[]{IGamePlayer.class},handler);
        proxy.login("testuser","testpassword");
        proxy.killBoss();
        proxy.upgrade();
    }
}
interface IGamePlayer {
    //登录游戏
    void login(String user,String password);
    //杀怪
    void killBoss();
    //升级
    void upgrade();
}
class GamePlayer implements IGamePlayer{

    private String name;

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

    @Override
    public void login(String user, String password) {
        System.out.println("登录用户名:" + user + ",密码:" + password + ".");
    }

    @Override
    public void killBoss() {
        System.out.println(this.name + "在打怪.");
    }

    @Override
    public void upgrade() {
        System.out.println(this.name + "又升级了!");
    }
}
class GamePlayerIH implements InvocationHandler{
    //被代理者
    Class cls = null;
    //被代理的实例
    Object obj;
    //我要代理谁
    public GamePlayerIH(Object obj) {
        this.obj = obj;
    }
    //调用被代理的方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(this.obj,args);
        return result;
    }
}
代码示例 1-2(优化)
public class Client8 {
    public static void main(String[] args) {
        IGamePlayer player = new GamePlayer("测试用户");
        InvocationHandler handler = new GamePlayerIH(player);
        ClassLoader cl = player.getClass().getClassLoader();
        //动态产生一个代理者
        IGamePlayer proxy = (IGamePlayer) Proxy.newProxyInstance(cl,new Class[]{IGamePlayer.class},handler);
        proxy.login("testuser","testpassword");
        proxy.killBoss();
        proxy.upgrade();
    }
}
interface IGamePlayer {
    //登录游戏
    void login(String user,String password);
    //杀怪
    void killBoss();
    //升级
    void upgrade();
}
class GamePlayer implements IGamePlayer{

    private String name;

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

    @Override
    public void login(String user, String password) {
        System.out.println("登录用户名:" + user + ",密码:" + password + ".");
    }

    @Override
    public void killBoss() {
        System.out.println(this.name + "在打怪.");
    }

    @Override
    public void upgrade() {
        System.out.println(this.name + "又升级了!");
    }
}
class GamePlayerIH implements InvocationHandler {
    //被代理者
    Class cls = null;
    //被代理的实例
    Object obj;
    //我要代理谁
    public GamePlayerIH(Object obj) {
        this.obj = obj;
    }
    //调用被代理的方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(this.obj,args);
        //如果是登录方法,则发送信息
        if(method.getName().equalsIgnoreCase("login")){
            System.out.println("有人在用我的账号登录!");
        }
        return result;
    }
}

案例 2(动态代理模板)

描述

动态代理实现代理的职责,业务逻辑 Subject 实现相关的逻辑功能,两者之间没有必然的相互耦合关系。通知 Advice 从另一个切面切入,最终在高层模块也就是 Client 进行耦合,完成逻辑的封装任务。

图形结构(动态代理通用类图)

image.png

代码示例 1-1
public class Client9 {
    //动态代理场景
    public static void main(String[] args) {
        //定义一个主题
        Subject subject = new RealSubject();
        //定义一个Handler
        InvocationHandler handler = new MyInvocationHandler(subject);
        //定义主题的代理
        Subject proxy = DynamicProxy.newProxyInstance(
                                        subject.getClass().getClassLoader(),
                                        subject.getClass().getInterfaces(),
                                        handler);
        //代理的行为,当这里和输出"3"的地方打debug时候"3"这个会输出多行
        proxy.doSomething("finish");

        System.out.println("..............");

    }
}

/**
 * 抽象主题
 */
interface Subject{
    //业务操作
    void doSomething(String str);
}

/**
 * 真实主题
 */
class RealSubject implements Subject{
    //业务操作
    @Override
    public void doSomething(String str) {
        System.out.println("-----------doSomething--------->" + str);
    }
}

/**
 * 动态代理的Handler类
 */
class MyInvocationHandler implements InvocationHandler{

    //被代理的对象
    private Object target = null;

    //通过构造函数传递一个对象
    public MyInvocationHandler(Object target) {
        this.target = target;
    }
    //代理方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //执行被代理的方法
        //所有通过动态代理实现的方法全部通过invoke方法调用
        System.out.println("33333333333333333333");
        return method.invoke(this.target,args);
    }
}

/**
 * 动态代理类
 * (这里插入了较多的AOP术语,如在什么地方/连接点执行什么行为/通知)
 * @param <T>
 */
class DynamicProxy<T>{
    public static <T> T newProxyInstance(
            ClassLoader loader,Class<?>[] interfaces,InvocationHandler handler){
        System.out.println("1111111111111111111111");
        //寻找JoinPoint的连接点,AOP框架使用元数据定义
        if(true){
            //执行一个前置通知
            (new BeforeAdvie()).exec();
        }
        System.out.println("222222222222222222222");
        //执行目标并返回结果
        return (T) Proxy.newProxyInstance(loader,interfaces,handler);
    }
}

/**
 * 通知接口(要切入的类)
 */
interface IAdvice{
    //通知只有一个方法,执行即可。
    void exec();
}

/**
 * 通知接口实现
 */
class BeforeAdvie implements IAdvice{
    @Override
    public void exec() {
        System.out.println("我是前置通知,我被执行了!");
    }
}

输出结果:
1111111111111111111111
我是前置通知,我被执行了!
222222222222222222222
33333333333333333333
-----------doSomething--------->finish
描述及调用过程图示
有这段代码
“
this.obj = Proxy.newProxyInstance(
subject.getClass().getClassLoader(),subject.getClass().getInterfaces(),
new MyInvocationHandler(subject));
”

该方法是重新生成了一个对象,重新生成对象的原因是要使用代理,注意
“subject.getClass().getInterfaces()”这句话,是说查找到该类的所有接口,然后实现接口的所有方法。当然了,方法都是空的,由谁具体负责接管呢?是“new MyInvocationHandler(subject)”这个对象。于是我们知道一个类的动态代理类是这样的一个类,由InvocationHandler的实现类实现所有的方法,由其invoke方法接管所有方法的实现,其动态调用过程如下:

image.png

代码示例 1-2(优化)
加入业务相关的动态代理处理方式

public class Client10 {
    public static void main(String[] args) {

        //定义一个主题
        Subject subject = new RealSubject();
        //定义主题的代理
        Subject proxy = SubjectDynamicProxy.newProxyInstanceSubject(subject);
        proxy.doSomething("halou");

    }
}

/**
 * 抽象主题
 */
interface Subject{
    //业务操作
    void doSomething(String str);
}

/**
 * 真实主题
 */
class RealSubject implements Subject{
    //业务操作
    @Override
    public void doSomething(String str) {
        System.out.println("-----------doSomething--------->" + str);
    }
}

/**
 * 动态代理的Handler类
 */
class MyInvocationHandler implements InvocationHandler{

    //被代理的对象
    private Object target = null;

    //通过构造函数传递一个对象
    public MyInvocationHandler(Object target) {
        this.target = target;
    }
    //代理方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //执行被代理的方法
        //所有通过动态代理实现的方法全部通过invoke方法调用
        System.out.println("33333333333333333333");
        return method.invoke(this.target,args);
    }
}

/**
 * 动态代理类(通用类而不具有业务意义)
 * (这里插入了较多的AOP术语,如在什么地方/连接点执行什么行为/通知)
 * @param <T>
 */
class DynamicProxy<T>{
    public static <T> T newProxyInstance(
            ClassLoader loader,Class<?>[] interfaces,InvocationHandler handler){
        System.out.println("1111111111111111111111");
        //寻找JoinPoint的连接点,AOP框架使用元数据定义
        if(true){
            //执行一个前置通知
            (new BeforeAdvie()).exec();
        }
        System.out.println("222222222222222222222");
        //执行目标并返回结果
        return (T) Proxy.newProxyInstance(loader,interfaces,handler);
    }
}

/**
 * 动态代理业务实现类
 */
class SubjectDynamicProxy extends DynamicProxy{

    public static <T> T newProxyInstanceSubject(Subject subject){
        //获得ClassLoader
        ClassLoader loader = subject.getClass().getClassLoader();
        //获得接口数组
        Class<?>[] classes = subject.getClass().getInterfaces();
        //获得handler
        InvocationHandler handler = new MyInvocationHandler(subject);
        return newProxyInstance(loader,classes,handler);

    }
}
/**
 * 通知接口(要切入的类)
 */
interface IAdvice{
    //通知只有一个方法,执行即可。
    void exec();
}

/**
 * 通知接口实现
 */
class BeforeAdvie implements IAdvice{
    @Override
    public void exec() {
        System.out.println("我是前置通知,我被执行了!");
    }
}


输出结果:
1111111111111111111111
我是前置通知,我被执行了!
222222222222222222222
33333333333333333333
-----------doSomething--------->halou

以上的动态代理是一个通用代理框架。如果想设计自己的 AOP 框架,完全可以在此基础上扩展,这里设计的是一个通用代理,只要有一个接口,一个实现类,就可以使用该代理,完成代理的所有功效。

与静态代理区别

看“父类”DynamicProxy,动态代理的主要意图就是解决我们常说的“审计”问题,也就是横切面编程,在不改变我们已有代码结构的情况下增强或控制对象的行为。

实现动态代理的首要条件

1、被代理类必须实现一个接口;2、CGLIB。

最佳实践 AOP

对 SpringAOP 和 AspectJ 这样优秀的工具进行调试时,只要看到 $Proxy()这样的结构,就应该知道这是一个动态代理了。

在学习 SpringAOP 框架时,只要弄清这几个名词就成:切面(Aspect),切入点(JoinPoint),通知(Advice),织入(Weave)就足够了。


标题:设计模式(四)结构型模式(对象结构型模式)代理模式-PROXY
作者:yazong
地址:https://blog.llyweb.com/articles/2020/05/13/1589302717589.html