java动态代理

代理

  • 代理:充当中介,当A不能直接访问C时,需找一个中介,A->B->C,B就是代理。

  • 代理模式:通过代理方来操作目标对象,而不是自己直接调用。

  • 使用代理模式的作用:

    • 功能增强:在已有的功能上增加其他的功能。
    • 控制访问:代理类不让调用方直接访问被调用方。
  • 实现代理的方式:

  • 静态代理static-proxy:代理类是自己创建一个java类手工实现,表示代理类,明确要代理的目标。

    • 优点:实现简单、容易理解。
    • 缺点:当目标类增加,代理类可能需成倍增加。当接口中的功能修改时,会影响实现类。不符合开闭(OCP)原则。目标类越多影响范围越大。
  • 动态代理:在静态代理中目标类很多时,可采用动态代理。动态代理中的目标类及时很多,代理类也可以很少,,修改接口中的方法时,不会影响代理类

    • 动态代理使用JDK的反射机制,创建代理类对象,并动态的指定要代理的目标类,代理类是活动的,可设置的。

      Class.forNAme(String);
      
    • 动态:在程序执行时,通过JDK创建代理类对象。

    • 特点:不用创建代理类,可以给不同的目标随时创建代理

动态代理
  • 实现方式有两种:

    • JDK动态代理:使用java反射包中的类和接口实现动态代理的功能。要求目标类中必须有接口。

      //全限定名
          java.lang.reflect.InvocationHandler
          java.lang.reflect.Method
          java.lang.reflect.Proxy
      
    • cglib动态代理:cglib是第三方工具库,创建代理对象,Cglib的原理是继承,通过继承目标类,创建它的子类,在子类中重写父类中的同名方法,实现功能修改。

    • 因为Cglib是通过继承重写实现,要求目标类不能为Final的,方法也不能为Final的。

    JDK动态代理

    反射,通过Method类,表示方法,类中的某个方法,通过Method可以执行某方法。

    //伪代码
    //代理类
    A a = new A();
    //通过反射调用代理类的方法
    Method method = A.class.getMethod(方法名,方法参数类型)//执行方法,返回方法返回对象
    Object obj = method.invoke(a,方法参数)
    

    JDk动态代理的实现

    1)InvocationHandler(调用处理器)接口:只有一个方法invoke()

    ​ invoke():表示代理对象要执行的功能代码,代理类功能写在invoke()中。

    ​ 代理类完成的功能:1、调用目标方法,执行目标方法的功能。2、功能增强,在目标方法调用时,增加功能。

    //方法原型
        //参数 Object proxy:JDK创建的代理对象,无需赋值
        //参数 Method method: 目标类的方法,JDK提供Method对象。
        //参数 Object... args:method方法中的执行参数。JDK提供的
        public Object invoke(Object proxy, Method method, Object[] args)
    

    怎么用?

    1、创建类实现接口InvocationHandler,实际上InvocationHandler接口表示你的代理要干什么。

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

    2)Method类,表示方法的,确切的说就是目标类中的方法,通过Methed可以执行某个目标类的方法。

    method.invoke(目标对象,方法的参数)Object obj = method.invoke(目标对象,方法的参数);
    

    3)Proxy类:核心的对象,创建的代理对象。

    方法:静态方法 newProxyInstance()

    作用是:创建代理对象,等同与静态代理中的new一个对象。

    //参数 ClassLoader 类加载器,负责向内存中加载对象的,使用反射获取对象的ClassLoader
        类a,a.getClass().getClassLoader(),目对象的类加载器
    //参数 Class<?>[] interfaces 接口,目标对象实现的接口,也是反射获取的
    //参数 InvocationHandler h 自己写的 代理类要完成的功能
       //返回值:代理对象
    public static Object newProxyInstance(ClassLoader loader,   Class<?>[] interfaces,
                                              InvocationHandler h)
    

    实现动态代理的步骤:

    1、创建接口,定义目标类要完成的功能。

    2、创建目标类实现接口。

    3、创建InvocationHandler接口实现类,在Invoke()方法中完成代理类的功能。

    1)调用目标方法。

    2)实现增强方法。

    4、使用Proxy类的静态方法,创建代理对象,并把返回值转为接口类型。

    动态代理的使用场景:

    1、可以在不改变原来的目标方法功能前提下,在代理中增强自己的功能代码。

    //示例代码
    public class testProxy {
        public static void main(String[] args) {
            //声明被代理对象
            SayHelloPlus sayHelloPlus = new SayHelloPlus();
            //调用发掉用处理器
            InvocationHandler invo = new Myhandler(sayHelloPlus) {};
            HelloServic proxyInstance = (HelloServic) Proxy.newProxyInstance(sayHelloPlus.getClass().getClassLoader(),
                    sayHelloPlus.getClass().getInterfaces(), invo);
            //调用动态代理对象对象方法
            proxyInstance.sayHello("helloKitty");
    
        }
     
    
    //被代理接口
    public interface HelloServic {
        public void sayHello(String name);
    }
    
    //被代理功能
    public class SayHelloPlus implements HelloServic {
        @Override
        public void sayHello(String name) {
            System.out.println("Hello " + name);
        }
    }
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    //实现代理功能 与增强功能
    public class Myhandler implements InvocationHandler {
        Object target;
        public Myhandler(Object target) {
            this.target = target;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("Plus+++++");
            return method.invoke(target, args);
        }
    }
    
  • 32
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值