动态代理

复习反射

反射的定义:在运行状态时(动态的),对于任意一个类,都能够得到这个类的所有属性和方法。对于任意一个对象,都能够调用它的任意属性和方法。这种动态获取的信息以及动态调用对象的方法的功能称之为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);
    }
}
原文地址:https://www.cnblogs.com/hello-liu/p/14811300.html