设计模式(4)——代理模式

本文深入解析了代理模式的三种实现方式:静态代理、动态代理和Cglib代理。通过实例代码展示了每种代理模式的工作原理,以及它们在不同场景下的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 定义

Provide a surrogate or placeholder for another object to control access to it.
 
为其他对象提供一种代理以控制对这个对象的访问。

2. 代码

2.1 静态代理

	静态代理中,代理对象和目标对象都需要实现抽象类。

抽象类:

//抽象接口供目标对象和代理对象继承
public abstract class AbstractObject {
    protected abstract void doSomething();
}

目标对象:

//目标对象实现抽象类
public class RealObject extends AbstractObject {
    @Override
    protected void doSomething() {
        System.out.println("目标对象执行了一些操作");
    }
}

代理对象:

//代理对象实现抽象类
public class ProxyObject extends AbstractObject {
    //要执行的实现抽象类的具体类
    private AbstractObject object;

    public ProxyObject(AbstractObject object) {
        this.object = object;
    }

    @Override
    protected void doSomething() {
        System.out.println("代理对象执行目标对象操作前");
        object.doSomething();
        System.out.println("代理对象执行目标对象操作后");
    }
}

测试类:

public class TestMain {
    public static void main(String[] args) {
        //静态代理
        System.out.println("静态代理");
        //传入需要代理的具体类
        ProxyObject object = new ProxyObject(new RealObject());
        //代理对象执行逻辑
        object.doSomething();
    }
}

结果:

	静态代理
	代理对象执行目标对象操作前
	目标对象执行了一些操作
	代理对象执行目标对象操作后

静态代理可以在不改变目标对象的情况下扩展功能,但是必须和目标对象实现相同的接口或抽象类,一旦接口增加方法,两者都要维护,所以可使用动态代理。

2.2 动态代理

	动态该代理中,代理对象不需要实现目标对象实现的抽象类。

动态代理实现,需要用到newProxyInstance()方法,接收三个参数。即newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

抽象类接口:

//登陆接口-目标对象要实现的接口
public interface IUserLogin {
    void saveUserName();
}

目标对象:

//目标对象实现抽象接口
public class User implements IUserLogin {
    @Override
    public void saveUserName() {
        System.out.println("用户登陆后已经保存了用户名");
    }
}

动态代理对象:

//动态对象,不需要实现目标对象实现的接口
public class DynamicProxyObject {
    private Object object;//目标对象

    public DynamicProxyObject(Object object) {
        this.object = object;
    }

    public Object getDynamicProxyInstance() {
        return Proxy.newProxyInstance(
                object.getClass().getClassLoader(),
                object.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("代理对象执行目标对象方法前");
                        Object value = method.invoke(object, args);
                        System.out.println("代理对象执行目标对象方法后");
                        return value;
                    }
                }
        );
    }
}

测试类:

public class TestMain {
    public static void main(String[] args) {
        //静态代理
        System.out.println("静态代理");
        //传入需要代理的具体类
        ProxyObject object = new ProxyObject(new RealObject());
        //代理对象执行逻辑
        object.doSomething();
        
        //动态代理
        System.out.println("-------------\n动态代理");
        IUserLogin user = new User();
        //传入目标对象
        DynamicProxyObject dynamicProxyObject = new DynamicProxyObject(user);
        //调用未实现接口动态代理对象的方法,获取实现接口的代理对象
        IUserLogin proxy = (IUserLogin) dynamicProxyObject.getDynamicProxyInstance();
        proxy.saveUserName();//调用方法才会执行
    }
}

结果:

	静态代理
	代理对象执行目标对象操作前
	目标对象执行了一些操作
	代理对象执行目标对象操作后
	-------------
	动态代理
	代理对象执行目标对象方法前
	用户登陆后已经保存了用户名
	代理对象执行目标对象方法后

2.3 Cglib代理

目标对象不需要实现抽象类或接口时,可使用Cglib代理
需要先引入Cglib的jar包,如果报错的话,可能还需要引用asm的jar包点击下载
版本不对可能会出错,我使用的是cglib-2.2.2asm-3.3版本的。

未实现接口的目标对象:

//没有接口实现的目标对象
public class User2 {
    public void saveUserName() {
        System.out.println("用户2登陆后已经保存了用户名");
    }
}

内存中动态创建子类对象

public class DynamicCglibProxyObject implements MethodInterceptor{
    private Object object;
	//传入目标对象
    public DynamicCglibProxyObject(Object object) {
        this.object = object;
    }
	
    public Object getCglibProxyInstance() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(object.getClass());
        //回调
        enhancer.setCallback(this);
        //创建代理对象返回
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
     throws Throwable {
        System.out.println("代理对象执行目标对象方法前");
        Object value = method.invoke(object, objects);
        System.out.println("代理对象执行目标对象方法后");
        return value;
    }
}

测试类:

public class TestMain {
    public static void main(String[] args) {
        //静态代理
        System.out.println("静态代理");
        //传入需要代理的具体类
        ProxyObject object = new ProxyObject(new RealObject());
        //代理对象执行逻辑
        object.doSomething();

        //动态代理
        System.out.println("-------------\n动态代理");
        IUserLogin user = new User();
        //传入目标对象
        DynamicProxyObject dynamicProxyObject = new DynamicProxyObject(user);
        //调用未实现接口动态代理对象的方法,获取实现接口的代理对象
        IUserLogin proxy = (IUserLogin) dynamicProxyObject.getDynamicProxyInstance();
        proxy.saveUserName();//调用方法才会执行

        //Cglib代理,目标对象没有实现接口的动态代理
        System.out.println("-------------\nCglib代理");//jar包版本号需要对应,有很多错误
        User2 user2 = new User2();
        DynamicCglibProxyObject dynamicCglibProxyObject = new DynamicCglibProxyObject(user2);
        User2 proxy2 = (User2) dynamicCglibProxyObject.getCglibProxyInstance();
        proxy2.saveUserName();
    }
}

结果:

	静态代理
	代理对象执行目标对象操作前
	目标对象执行了一些操作
	代理对象执行目标对象操作后
	-------------
	动态代理
	代理对象执行目标对象方法前
	用户登陆后已经保存了用户名
	代理对象执行目标对象方法后
	-------------
	Cglib代理
	代理对象执行目标对象方法前
	用户2登陆后已经保存了用户名
	代理对象执行目标对象方法后
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值