(代理模式)静态代理、JDK动态代理、CGLIB动态代理

静态代理设计模式

基本概念

通过代理类的对象,为原始类的对象(目标类的对象)添加辅助功能,更容易更换代理实现类、利于维护。

静态代理
在这里插入图片描述

优缺点

  • 代理类 = 实现原始类相同接口 + 添加辅助功能 + 调用原始类的业务方法。
  • 静态代理的问题
    • 代理类数量过多,不利于项目的管理。
    • 多个代理类的辅助功能代码冗余,修改时,维护性差。​

代码实例

Business 业务接口

package com.qianfeng.workone.example.dynamic;

public interface Business {

    void sing(String singName);

    void dance();

    Integer price(int price);

}

Actor演员类

package com.qianfeng.workone.example.dynamic;

public class Actor implements Business{
    @Override
    public void sing(String singName) {
        System.out.println("在舞台上面唱" + singName);
    }

    @Override
    public void dance() {
        System.out.println("在舞台上尽情跳舞");
    }

    @Override
    public Integer price(int price) {
        System.out.println("结算薪资是" + price);
        return price;
    }
}

Bbroker经纪人类

package com.qianfeng.workone.example.dynamic;

public class Broker implements Business{

    private Actor actor;

    public Broker() {
    }

    public Broker(Actor actor) {
        this.actor = actor;
    }

    @Override
    public void sing(String singName) {
        System.out.println("经纪人在外谈好活动");
        actor.sing(singName);
        System.out.println("经纪人在内做好后续工作");
    }

    @Override
    public void dance() {
        System.out.println("经纪人在外谈好活动");
        actor.dance();
        System.out.println("经纪人在内做好后续工作");
    }

    @Override
    public Integer price(int price) {
        System.out.println("经纪人在外谈好活动");
        Integer price1 = actor.price(price + 5000);
        System.out.println("经纪人在内做好后续工作");
        return price1;
    }
}

Test测试类

package com.qianfeng.workone.example.dynamic;

public class Test {
    public static void main(String[] args) {
        Actor actor = new Actor();
        Broker broker = new Broker(actor);
        broker.sing("征服");
        broker.dance();
        broker.price(10000);
    }
}

运行结果
在这里插入图片描述

JDK动态代理

基本概念

动态创建代理类的对象,为原始类的对象添加辅助功能。
在原有的静态代理基础上,功能相同但是不被接口中方法中数量所限制,能够动态的在方法前后添加辅助功能

优缺点

在之前的静态代理的基础上可以发现,
有如下规律:在代理类中被代理类的对象方法的前后处理都相同,出现的大量的代码冗余。
在动态代理中内部通过反射的方式将前后处理动态的加载到每一个代理类方法的前后,不被方法的个数和类型所限制。
缺陷就是代理类必须要实现接口

代码实例

Business 业务接口

package com.qianfeng.workone.example.dynamic;

public interface Business {

    void sing(String singName);

    void dance();

    Integer price(int price);

}

Actor演员类

package com.qianfeng.workone.example.dynamic;

public class Actor implements Business{
    @Override
    public void sing(String singName) {
        System.out.println("在舞台上面唱" + singName);
    }

    @Override
    public void dance() {
        System.out.println("在舞台上尽情跳舞");
    }

    @Override
    public Integer price(int price) {
        System.out.println("结算薪资是" + price);
        return price;
    }
}

ProxyFactory 代理类的工厂

package com.qianfeng.workone.example.dynamic;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyFactory {

    public static Object proxy(Object obj){
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("经纪人在外谈好活动");
                Object invoke = method.invoke(obj, args);
                System.out.println("经纪人在内做好后续工作");
                return invoke;
            }
        });
    }
    //通过方法泛型的方式能够避免强制类型转换
    public static <T> T proxyObject(T obj){
        return (T)Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("经纪人在外谈好活动");
                Object invoke = method.invoke(obj, args);
                System.out.println("经纪人在内做好后续工作");
                return invoke;
            }
        });
    }

}

ProxyTest 测试类

package com.qianfeng.workone.example.dynamic;

import com.sun.xml.internal.bind.v2.model.core.EnumLeafInfo;

public class ProxyTest {
    public static void main(String[] args) {
        Actor actor = new Actor();
        ProxyFactory proxyFactory = new ProxyFactory();
        Business proxy = (Business) proxyFactory.proxy(actor);
        proxy.sing("征服");
        proxy.dance();
        proxy.price(15000);

        System.out.println("=================以下为泛型的使用方式,通用性更好==================");

        Business proxyObject = proxyFactory.proxyObject(actor);
        proxyObject.sing("动物世界");
        proxyObject.dance();
        proxyObject.price(18000);

    }

}

结果截图
在这里插入图片描述

CGLIB动态代理

基本概念

跟jdk原生的动态代理没有什么区别

优缺点

在JDK的基础上能够实现没有实现接口也能够动态代理一个类

代码实例

Actor 被代理类

package com.qianfeng.workone.example.dynamiciscglib;

public class Actor{

    public void sing(String singName) {
        System.out.println("在舞台上面唱" + singName);
    }


    public void dance() {
        System.out.println("在舞台上尽情跳舞");
    }


    public Integer price(int price) {
        System.out.println("期望薪资是" + price);
        return price;
    }
}

ProxyFactor 在此类中处理代理类中的细节(取名不严谨)

package com.qianfeng.workone.example.dynamiciscglib;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class ProxyFactory implements MethodInterceptor {
	
	private Actor actor = new Actor();
	
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        //其中o代表被代理类本身,method代表被代理类的响应方法,objects代表被代理类传入的参数,MethodProxy暂不清楚,但是要这要用
        System.out.println("代理类的准备工作");
        //调用方法一
        Object obj = methodProxy.invokeSuper(o, objects);
        //调用方法二
        Object obj = method.invoke(actor,objects);
        System.out.println("代理类的收尾工作");
        System.out.println();
        return obj;
    }
}

ProxyTest 测试类

package com.qianfeng.workone.example.dynamiciscglib;

import net.sf.cglib.proxy.Enhancer;

public class ProxyTest {
    public static void main(String[] args) {
        //设置一个增强器
        Enhancer enhancer = new Enhancer();

        //设置要生成代理的类的父类
        enhancer.setSuperclass(Actor.class);

        // 设置一个回调,每次通过代理对象来调用方法的时候,都会进入到对应拦截器中。
        enhancer.setCallback(new ProxyFactory());

        Actor actor = (Actor) enhancer.create();
        actor.sing("演员");
        actor.dance();
        actor.price(10000);
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值