设计模式之代理模式

1、基本介绍:
为对象提供一个替身,以控制对这个对象的访问。即通过代理对象访问目标对象,这样的好处是可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。
代理模式可分为静态代理和动态代理,动态代理包括JDK代理和cglib代理,下面依次介绍

2、静态代理:
静态代理需要定义接口或者父类,被代理对象(即目标对象)与代理对象一起实现相同的接口或者是继承相同的父类。
定义一个接口:

public interface MyInterface {
    void solve(String name);
}

被代理类实现这个接口:

public class MyImpl implements MyInterface {
    @Override
    public void solve(String name) {
        System.out.println(name+"调用了该方法");
    }
}

代理类实现同样一个接口并且持有一个被代理对象的引用:

public class MyProxy implements MyInterface{
    private MyInterface myInterface;

	public MyProxy(MyInterface myInterface){
		this.myInterface = myInterface;
	}
	
    @Override
    public void solve() {
        System.out.println("Before......" );
        myInterface .solve();
        System.out.println("After......");
    }
}

使用代理类:

public static void main(String[] args) {
		// 创建被代理类对象
		MyInterface myInterface = new MyImpl("bipa");
        // 创建代理类对象
        MyProxy myProxy = new MyProxy(myInterface);
        // 调用方法
        myProxy .solve();
    }

静态代理优缺点:

  • 在不修改目标对象的功能前提下,能通过代理对象对目标功能扩展
  • 由于代理对象需要与目标对象实现一样的接口,所以会有很多代理类
  • 一旦接口增加方法,目标对象与代理对象都要维护

3、动态代理
3.1、JDK动态代理
基本介绍:

  • 代理对象不需要实现接口,但是目标对象要实现接口
  • 利用JDK的API动态的在内存中构建代理对象
  • JDK动态代理又叫接口代理

具体步骤:

  • 通过实现 InvocationHandler 接口创建自己的调用处理器
  • 通过为 Proxy 类指定被代理类的 ClassLoader 对象和一组 interface 来创建动态代理类
  • 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型
  • 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入

代码实现如下:

public class TestJDKProxy {
    public static void main(String[] args) {
        MyImpl myImpl = new MyImpl();
        MyInterface mi = (MyInterface) Proxy.newProxyInstance(myImpl.getClass().getClassLoader(),myImpl.getClass().getInterfaces(),
                (proxy,method,arg) -> {
                    System.out.println("前");
                    Object res = null;
                    res = method.invoke(myImpl,arg);
                    System.out.println("后");
                    return res;
                });
        mi.solve("bipa");
    }
}

JDK动态代理底层使用反射机制进行方法的调用,不过只能够代理实现了接口的委托类。

3.2、Cglib代理
基本介绍:

  • 静态代理和JDK代理都要求目标对象实现一个接口,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候可使用目标对象子类来实现代理,即Cglib代理
  • Cglib代理也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能扩展
  • Cglib是一个强大的高性能的代码生成包,可以在运行期扩展java类与实现java接口,广泛的被许多AOP框架使用,如Spring AOP,实现方法拦截
  • Cglib包的底层是通过使用字节码处理框架ASM来转换字节码并生成新的类

代码演示:
引入第三方包

<dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>3.3.0</version>
    </dependency>

定义被代理类

public class MyImpl {
    public void solve(){
        System.out.println("solving...");
    }
}

定义方法拦截器

public class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("Before:"+method.getName());
        Object object = methodProxy.invokeSuper(o,objects);
        System.out.println("After:"+method.getName());
        return object;
    }
}

生成代理类对象并调用方法

public class Client {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(MyImpl.class);// 继承被代理类
        enhancer.setCallback(new MyMethodInterceptor());// 设置回调
        MyImpl my = (MyImpl) enhancer.create();// 生成代理类对象
        my.solve();// 使用代理类调用方法时会被实现的方法拦截器拦截
    }
}
运行结果
Before:solve
solving...
After:solve

注意:Cglib不能对final类以及final/static方法进行代理。

至此,代理模式的介绍完毕

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

b17a

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值