zoukankan      html  css  js  c++  java
  • 动态代理

    复习反射

    反射的定义:在运行状态时(动态的),对于任意一个类,都能够得到这个类的所有属性和方法。对于任意一个对象,都能够调用它的任意属性和方法。这种动态获取的信息以及动态调用对象的方法的功能称之为java语言的反射机制.

    反射的三种用法

    public class ClassDemo02 {
    
         public static void main(String[] args) {
              Person p1 = new Person("小明" ,20,'男' );
              Person p2 = new Person("小红" ,23,'女' );
    
               //创建Class对象的方式一:(对象.getClass()),获取person类中的字节码文件
               Class class1 = p1.getClass();
              System. out.println(p1.getClass().getName());
               Class class2 = p2.getClass();
              System. out.println(class1 == class2 );
    
              System. out.println("==============================" );
               //创建Class对象的方式二:(类.class:需要输入一个明确的类,任意一个类型都有一个静态的class属性)
               Class class3 = Person.class;
              System. out.println(class1 == class2);
    
              System. out.println("==============================" );
               //创建Class对象的方式三:(forName():传入时只需要以字符串的方式传入即可)
               //通过Class类的一个forName(String className)静态方法返回一个Class对象,className必须是全路径名称;
               //Class.forName()有异常:ClassNotFoundException
    
               Class class4 = null;
               try {
                  class4 = Class.forName("cn.itcast.Person");
              } catch (ClassNotFoundException e) {
                   // TODO Auto-generated catch block
                  e.printStackTrace();
              }
              System. out.println(class4 == class3);
         }
    }
    
    

    动态代理

    对于JDK动态代理,其必须要有接口
    代码案例
    接口

    package bjpowernode;
    
    public interface HelloService {
         void sayhello(String name);
    }
    

    方法HelloServiceimpl

    package bjpowernode.Service;
    
    import bjpowernode.HelloService;
    
    public class HelloServiceimpl implements HelloService {
        @Override
        public void sayhello(String name) {
            System.out.println("你好:"+name);
        }
    }
    

    被代理的方法TestApp

    package bjpowernode;
    
    import bjpowernode.Service.HelloServiceimpl;
    
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    public class TestApp {
        public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
            HelloService service = new HelloServiceimpl();
    
            service.sayhello("zhangsan");
    
    
    
            //使用反射机制执行sayhello方法
            HelloService target = new HelloServiceimpl();
            //获取hello名称对饮的Method类对象
            //关于.class.getMethod()方法:作用是获得对象所声明的公开方法,该方法的第一个参数name是要获得方法的名字,第二个参数parameterTypes是按声明顺序标识该方法形参类型。
            //在sayhello方法中,方法的类型是String,因此第二个参数为String.class
            Method method = HelloService.class.getMethod("sayhello", String.class);
    
    
            //通过method可以调用sayhello方法
    		//表达的意思是method方法执行的对象是sayhello,参数是李四
            method.invoke(target,"李四");
        }
    }
    
    

    动态代理分析
    反射包 java.lang.reflect , 里面有三个类 : InvocationHandler , Method, Proxy.
    1)InvocationHandler 接口(调用处理器):就一个方法invoke()
    invoke():表示代理对象要执行的功能代码。你的代理类要完成的功能就写在 invoke()方法中。

    代理类完成的功能:
    1. 调用目标方法,执行目标方法的功能
    2. 功能增强,在目标方法调用时,增加功能。
    方法原型
    参数: Object proxy:jdk创建的代理对象,无需赋值.Method method:目标类中的方法,jdk提供method对象的Object[] args:目标类中方法的参数, jdk提供的。

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

    InvocationHandler 接口:表示你的代理要干什么。
    怎么用: 1.创建类实现接口InvocationHandler
    2.重写invoke()方法, 把原来静态代理中代理类要完成的功能,写在这。

    2)Method类:表示方法的, 确切的说就是目标类中的方法。
    作用:通过Method可以执行某个目标类的方法,Method.invoke();

     method.invoke(目标对象,方法的参数)
    Object ret = method.invoke(service2, "李四");
    
     说明: method.invoke()就是用来执行目标方法的,等同于静态代理中的
    //向厂家发送订单,告诉厂家,我买了u盘,厂家发货
     float price = factory.sell(amount); //厂家的价格。
    

    3)Proxy类:核心的对象,创建代理对象。之前创建对象都是 new 类的构造方法()
    现在我们是使用Proxy类的方法,代替new的使用。
    方法: 静态方法 newProxyInstance()
    作用是: 创建代理对象, 等同于静态代理中的TaoBao taoBao = new TaoBao();

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

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

    动态代理实现步骤

     3. 实现动态代理的步骤:
        1. 创建接口,定义目标类要完成的功能
    	 2. 创建目标类实现接口
    	 3. 创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能
    	     1.调用目标方法
    		  2.增强功能
    
    	 4.使用Proxy类的静态方法,创建代理对象。 并把返回值转为接口类型。
    

    代码

    package Service;
    
    import Service.Handler.MySellHandler;
    
    import java.lang.reflect.Proxy;
    
    public class MainShop {
        public static void main(String[] args) {
            //创建代理对象,使用proxy
            UsbSell factory = new UsbKingFactory();
    
            //
    
    
    
            //创建InvocationHandler对象
    
            MySellHandler handler = new MySellHandler(factory);
            //创建目标对象
            UsbSell proxy_1 = (UsbSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(), factory.getClass().getInterfaces(), handler);
    
    
    
            //通过代理执行方法
            float sell = proxy_1.sell(1);
            System.out.println("通过动态代理得到的结果"+sell);
        }
    }
    
  • 相关阅读:
    flash模拟EEROM
    FATFS_SD卡
    AFIO
    ADC1多通道_DMA_内部温度传感器+内部VREFINT
    QmlBook--Meet Qt 5
    NRF24L01
    MWC飞控V2.3串口通信协议——new Multiwii Serial Protocol
    thread相关http://blog.csdn.net/forwayfarer/article/details/3455130
    comparable与comparator的区别http://blog.csdn.net/mageshuai/article/details/3849143
    ArrayList和LinkedList的区别http://pengcqu.iteye.com/blog/502676
  • 原文地址:https://www.cnblogs.com/hello-liu/p/14811300.html
Copyright © 2011-2022 走看看