spring-07.动态代理

1.使用代理模式的作用
  • 功能增强:在你原有的功能上,增加了额外的功能,新增的功能,叫做功能增强
  • 控制访问:代理类不让你访问目标,例如商家不让用户访问厂家
2.静态代理

模拟一个用户购买U盘的行为
用户是客户端类
商家:代理,代理某个品牌的u盘
厂家:目标类
三者的关系:用户(客户端)–商家(代理)–厂家(目标)
实现步骤:

  • 创建一个接口,定义卖U盘的方法,表示你的厂家和商家做的事情
  • 创建厂家类,实现1步骤的接口
  • 创建商家,就是代理,也需要实现1步骤的接口
  • 创建客户端类,调用商家的方法买U盘

具体实现为:

  • 创建一个接口
//表示功能的,厂家、商家都要完成的功能
public interface UsbSale {
    //定义方法
    //返回值表示一个U盘的价格
    float sell(int amout);
}

  • 创建厂家类继承接口
//目标类:金士顿厂家
public class UsbKingFactory implements UsbSale {
    @Override
    public float sell(int amout) {
        return 83.0f;
    }
}
  • 创建商家类继承接口,需调用厂家的方法
//淘宝是一个商家,代理金士顿的销售
public class TaoBao implements UsbSale {

    private UsbKingFactory factory=new UsbKingFactory();
    @Override
    //实现销售U盘的功能
    public float sell(int amout) {
        //向厂家发送订单,告诉厂家我要买U盘
        float price=factory.sell(amout);//厂家的价格

        price=price+20; //增强功能
        return price;
    }
}
  • 定义主方法
 public static void main(String[] args) {
        TaoBao taoBao=new TaoBao();
        float price=taoBao.sell(1);
        System.out.println("通过淘宝的商家,购买U盘"+price);
        }
3.动态代理

1.概念:在程序的执行过程中,使用jdk的反射机制创建代理,并动态的指定要代理的目标,动态代理是一种创建java对象的能力,
不用创建Taobao类,就能创建代理类对象,即不用创建代理类,可以给目标随时创建代理类
2.实现方式:

  • jdk动态代理:使用java反射包中的类和接口实现动态代理的功能,反射包 java.lang.reflect,里面有三个类:InvocationHandler、Method、Proxy
  • cglib动态代理:cglib是第三方的工具库,创建代理对象,cglib的原理是继承,cglib通过继承目标类,创建它的子类,在子类中重写父类中同名的方法,实现功能的修改。

3.method方法

  • 创建service类
public interface HelloService {
    public void sayHello(String name);
}
  • 创建service的实现类
public class HelloServiceImpl implements HelloService {
    @Override
    public void sayHello(String name) {
        System.out.println("你好"+name);
    }
}
  • 使用反射机制调用方法
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //HelloService helloService=new HelloServiceImpl();
        //helloService.sayHello("张三");


        //使用反射机制执行sayhello方法,核心method(类中的方法)
        HelloService target=new HelloServiceImpl();
        Method method=HelloService.class.getMethod("sayHello", String.class);
       //通过Method可以执行sayHello方法调用

        /**
         * invoke是method类中的一个方法,表示执行方法的调用
         * 参数:
         * 1.Object,表示要执行哪个对象的方法
         * 2.Object ...args,方法执行时的参数值
         * 返回值:
         * Object:方法执行后的返回值
         */

        //表达的意思是,执行target对象sayhello方法,参数是李四
        Object ret=method.invoke(target,"李四");

    }

4.InvocationHandler接口

  • InvocationHandler接口,就一个方法invoke()
  • invoke():表示代理对象要执行的功能代码,你的代理类要完成的功能就写在invoke()方法中
  • 代理类完成的功能:调用目标方法,执行目标方法功能;功能增强,在目标方法调用时,增加功能。
  • public object invoke(Object proxy,Method method,Object[] args)
  • 方法原理:
    参数:
    Object proxy:jdk创建的代理对象,无需赋值;
    Method method:目标类中的方法,jdk提供method对象;
    Object[] args:目标类中方法的参数,jdk提供的
  • 怎么用:
    创建类实现接口InvocationHandler;
    重写invoke()方法,把原来静态代理中代理类要完成的功能,写在这里
    5.Method类
  • 表示方法的,确切的说就是目标类中的方法
  • 作用:通过Method可以执行某个目标类的方Method.invoke();
  • method.invoke(目标对象,方法的参数)
    Object ret=method.invoke(service2,“lisi”);
    说明:method.invoke()就是用来执行目标方法的,这的invoke和上述接口中的invoke方法不同,只是恰巧同名
    6.Proxy类
  • 核心的对象,创建代理对象,之前创建对象都是new 类的构造方法(),现在我们是使用Proxy类的方法,代替new的使用
  • 方法:静态方法 newProxyInstance()
    作用是:创建代理对象,等同于静态代理中的new Taobao()
  • public static object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
  • 参数:
    ClassLoader loader 类加载器,负责向内存中加载对象的。使用反射获取对象的ClassLoader类a,a.getClass().getClassLoader()是目标对象的类加载器;
    Class<?>[] interfaces:目标对象实现的接口,也是反射获取的;
    InvocationHandler:我们自己写的,代理类要完成的功能
    7.实现动态代理的步骤:
  • 创建接口,定义目标类要完成的功能
  • 创建目标类实现接口
  • 创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能: 调用目标方法; 增加功能
  • 使用Proxy类的静态方法,创建代理对象,并把返回值转为接口类型
    8.实现
  • 创建接口
public interface UsbSell {
    float sell(int amout);
}
  • 创建目标类
public class UsbKingFactory implements UsbSell {
    @Override
    public float sell(int amout) {
        System.out.println("目标类中,执行sell目标方法");
        return 85.0f;
    }
}
  • 实现InvocationHandler接口,实现代理类要完成的功能
public class MySellHandler implements InvocationHandler {

    private Object target=null;
    //动态代理:目标对象是活动的,不是固定的,需要传入进来,传入是谁,就给谁创建代理
   public MySellHandler(Object target){
       this.target=target;
   }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		//定义返回值
        Object res=null;
        //其中args为参数,target为目标对象
        res=method.invoke(target,args);//执行目标对象的方法

        if(res!=null){
            Float price=(Float)res;
            price=price+25;
            res=price;
        }

        return res;
    }
}

  • 创建目标对象的代理
public static void main(String[] args) {

        //创建代理对象,使用Proxy
        //1.创建目标对象
        UsbSell factory=new UsbKingFactory();
        //2.创建InvocationHandler对象
        InvocationHandler handler=new MySellHandler(factory);

        //3.创建代理对象
        UsbSell proxy=(UsbSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(),
                factory.getClass().getInterfaces(),
                handler);
        //4.通过动态代理执行方法
        float price=proxy.sell(1);
        System.out.println("通过动态代理对象调用方法:"+price);
    }

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值