1动态代理

1. 动态代理的作用

功能增强:在原有的功能上,增加了额外的功能,叫做功能增强。

控制访问:代理类不让你访问目标,例如商家不让用户访问厂家

2. 实现动态代理的方法

静态代理

  1. 代理类是自己手工实现的,自己创建一个java类,表示代理类

  2. 同时你所要代理的目标类是确定的

优点:实现简单,容易理解

缺点:当项目中,目标类和代理类很多时,代理类数量过多,高耦合

模拟一个用户购买U盘的行为
1. 相关设计

a.用户是客户端类 b.商家:代理,代理某个品牌的U盘 c.厂家:目标类

三者的关系:用户(客户端)——商家(代理)——厂家(目标)

商家和厂家都是卖U盘的,他们完成的功能是一致的,都是卖U盘

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

1.目标类中方法的调用

2.功能增强

接口

package com.txy.service;
//表示功能的,厂家商家都要完成的功能
public interface UsbSell {
    //定义方法 参数 amount:表示一次购买的数量,暂时不用
    //返回值表示一个U盘的价格
    float sell(int amount);
}

厂家:UsbKingFactory

package com.txy.factory;

import com.txy.service.UsbSell;
//目标类:金士顿厂家,不接受用户的单独购买
public class UsbKingFactory implements UsbSell {
    @Override
    public float sell(int amount) {
        //一个128GU盘是85元
        //后期根据amount可以实现不同的价格,例如10000个,单价是80,一次买5000,单价是75
        return 85.0f;
    }
}

商家:TaoBao

package com.txy.seller;

import com.txy.factory.UsbKingFactory;
import com.txy.service.UsbSell;
//taobao是一个商家,代理金士顿U盘的销售
public class TaoBao implements UsbSell {
    //声明 商家代理的厂家具体是谁
    private UsbKingFactory factory = new UsbKingFactory();
    @Override
    //实现销售U盘的功能
    public float sell(int amount) {

        //向厂家发送订单,告诉厂家,我买了U盘,厂家发货
        float price = factory.sell(amount);    //厂家的价格
        //商家需要加价 也就是代理要增加价格
        price = price+25;   //增强功能,代理类在完成目标类方法调用后,增强了功能
        //在目标类的方法调用后,你做的其他功能,都是增强的意思。
        System.out.println("淘宝商家,给你返回优惠价或者红包");
        return price;
    }
}

客户端:ShopMain

package com.txy;

import com.txy.seller.TaoBao;

public class ShopMain {
    public static void main(String[] args) {
        //创建代理的商家taobao对象
        TaoBao taoBao = new TaoBao();
        float price = taoBao.sell(1);
        System.out.println("通过淘宝的商家购买U盘单价:"+price);
    }
}

动态代理

在静态代理中目标类很多时候,可以使用动态代理,避免静态代理的缺点

动态代理中目标类即使很多,代理数量可以很少,低耦合

动态代理:在程序执行过程中,使用jdk的反射机制,创建代理类对象,并动态的指定要代理目标类。换句话说:动态代理是一种创建java对象的能力,让你不用创建TaoBao类,就能创建代理类对象

1. 动态代理的实现
1.1 jdk动态代理:

使用java反射包中的类和接口实现动态代理的功能

反射包java.lang.reflect,里面有三个类:InvocationHandler,Method,Proxy

1.1.1 InvocationHandler接口:就一个方法invoke()

invoke():表示代理对象要执行的功能代码。你的代理类要完成的功能就写在invoke()方法之中

①方法原型:

public object invoke(Object proxy,Method method,Object[] args)

参数

1.Object proxy:jdk创建的代理对象,无需赋值

2.Method method:目标类中的方法,jdk提供method对象

3.Object[] args:目标类中方法的参数,jdk提供的

②怎么用:

InvocationHandler 接口:表示你的代理要干什么

1.创建实现接口InvocationHandler

2.重写invoke()方法,把原来静态代理中代理类要完成的功能,写在这

1.1.2 Method类:

表示方法的,确切的就是目标类中的方法

作用:通过Method可以执行某个目标类的方法,Method.invoke(目标对象,方法的参数)

Object ret = method.invoke(service2,"李四");

说明:method.invoke()就是用来执行目标方法的,等同义词静态代理中的

//向厂家发送订单,告诉厂家,我买了U盘,厂家发货
float price = factory.sell(amount);    //厂家的价格
1.1.3 Proxy类

核心的对象,创建代理对象。之前创建对象都是new 类的构造方法()

现在我们是使用Proxy类的方法,代替类的使用

方法:静态方法 newProxyInstance()

作用是:创建代理对象,等同于静态代理中的

TaoBao taoBao = new TaoBao();

方法原型:

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

参数:

  1. ClassLoader loader 类加载器,负责向内存中加载对象的。使用发射获取对象的ClassLoader 例如有类a,a.getclass().getClassLoader(),(获取目标对象的类加载器)
  2. Class<?>[] interfaces:接口,目标对象实现的接口,也是反射获取的
  3. InvocationHandler h:我们自己写的,代理类要完成的功能

返回值:就是代理对象

1.1.4 具体实现
  1. UsbSell接口: 定义目标类和代理类都要完成的行为
package com.txy.service;
public interface UsbSell {
    float sell(int amount);
}
  1. UsbKingFactory:目标类
package com.txy.factory;
import com.txy.service.UsbSell;
public class UsbKingFactory implements UsbSell {
    @Override
    public float sell(int amount) {
        //目标方法
        System.out.println("目标类中,执行sell目标方法");
        return 85;
    }
}
  1. MySellHandler:实现InvocationHandler接口,完成代理类要做的功能(1.调用目标方法,2.功能增强)
package com.txy.handler;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
//必须实现InvocationHandler接口,完成代理类要做的功能(1.调用目标方法,2.功能增强)
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;
        //float price = factory.sell(amount);
        res = method.invoke(target,args);//执行目标方法
        //price = price + 25;
        //增强功能
        if(res != null){
            Float price = (Float)res;
            price = price+25;
            res = price;
        }
        System.out.println("淘宝商家,给你返一个优惠劵,或者红包");
        return res;
    }
}

  1. MainApp
package com.txy
import com.txy.factory.UsbKingFactory;
import com.txy.handler.MySellHandler;
import com.txy.service.UsbSell;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class MainShop {
    public static void main(String[] args) {
        //创建代理对象,使用Proxy
        //1. 创建目标对象
        //也可以UsbKingFactory factory = new UsbKingFactory();但是接口接会更好
        UsbSell factory = new UsbKingFactory();
        //2. 创建invocationHandler对象
        InvocationHandler invocationHandler = new MySellHandler(factory);
        //2. 创建代理对象
        UsbSell proxy = (UsbSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(),
                            factory.getClass().getInterfaces(),
                            invocationHandler);
        //4. 通过代理执行方法
        float price = proxy.sell(1);
        System.out.println("通过动态代理调用方法结果是"+price);
    }
}
1.1.5 流程图

image-20210131205742950

1.2 cglib动态代理:

cglib是第三方的工具库,创建代理对象

cglib的原理是继承,cglib通过继承目标类,创建它的子类,在子类中重写父类同名的方法,实现功能的修改。

因为cglib是继承,重写方法,所以要求目标类不能是final的,方法也不能是final的

具体实现
  1. Target 目标类
package com.txy.proxy.cglib;
public class Target{
    public void save() {
        System.out.println("save save save hey running....................");
    }
}
  1. Advice 增强类
package com.txy.proxy.cglib;
public class Advice {
    public void before(){
        System.out.println("前置增强...................");
    }
    public void after(){
        System.out.println("后置增强...................");
    }
}
  1. 代理实现
package com.txy.proxy.cglib;

import com.txy.proxy.jdk.TargetInterface;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

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

public class ProxyTest {
    public static void main(String[] args) {
        //目标对象
        final Target target = new Target();
        //增强对象
        final Advice advice = new Advice();
        //返回值 就是动态生成的代理对象 基于cglib
        //1. 创建增强器
        Enhancer enhancer = new Enhancer();
        //2. 设置父类(目标)
        enhancer.setSuperclass(Target.class);
        //3. 设置回调 MethodInterceptor是Callback的一个实现类
        enhancer.setCallback(new MethodInterceptor() {
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                advice.before();//前置增强
                Object res = method.invoke(target, args);//执行目标
                advice.after();//后置增强
                return null;
            }
        });
        //4. 创建代理对象
        Target proxy = (Target)enhancer.create();
        proxy.save();

    }
}

对于无接口的类,要使用cglib来实现

hodProxy) throws Throwable {
advice.before();//前置增强
Object res = method.invoke(target, args);//执行目标
advice.after();//后置增强
return null;
}
});
//4. 创建代理对象
Target proxy = (Target)enhancer.create();
proxy.save();

}

}


**对于无接口的类,要使用cglib来实现**











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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值