在上一篇文章中,我们提到了,RPC框架所需要的java基础,第一点就是java的动态代理机制,动态代理机制的基础是反射,无论是在实际编程或者是面试时,都是java知识的重中之重。
java反射:
定义:
在运行状态中,对于任意一个类,都能够知道这一个类的所有属性和方法,对于任意一个对象都能够通过反射机制调用一个类的任意方法,这种动态获取类信息以及动态调用类方法的功能称为java的反射机制。
作用:
1、动态的创建类的实例,将类绑定到现有对象中,或从现有对象中获取类型。 2、应用程序需要在运行时从某个特定的程序集中载入一个特定的类。
个人理解的反射机制就是,某些类在程序运行的一开始并没有加载,但是随着程序的运行,我们发现这些类也需要用到,此时就可以通过反射机制,来获取到类的属性和方法。
代理模式:
定义:
委托模式,是为某个对象提供一个代理对象,并且由代理对象控制对原对象的访问。代理模式通俗来讲就是我们生活中常见的中介。代理模式可以提供非常好的访问控制,应用比较广泛。
而其中的代理模式中的动态代理不仅在rpc远程访问中有重要的应用,同样在Spring AOP和其他应用中也起到了很重要的作用。
代理模式的通用类图:

Subject: 抽象主题角色:可以是抽象类,也可以是接口。抽象主题是一个普通的业务类型,无特殊要求。
RealSubject: 具体主题角色:也叫做被委托角色或被代理角色,是业务逻辑的具体执行者。
Proxy: 代理主题角色:也叫做委托类或代理类。它负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实主题角色实现,并且在具体主题角色处理完毕前后做预处理和善后处理工作。
按照代理创建的时期来进行分类,可以分为动态代理和静态代理。
静态代理:
一个代理类只能实现一种抽象主题角色,在程序运行之前,代理类.class文件就已经被创建,代理类和委托类的关系在运行前就确定。
动态代理:
一个代理类通过反射机制,可以实现多种不类型的抽象主题角色。动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。以下为动态代理概括图:

实现代码块如下:
抽象角色类实现(动态代理的抽象决策类只能使用接口):
public interface Subject {
    /**
     * 接口方法,抽象主题类
     */
    public void request();
}具体决策类实现:
public class ConcreteSubject implements Subject{
    /**
     * 具体业务实现逻辑
     */
    @Override
    public void request() {
        //业务处理逻辑
        System.out.println("逻辑执行");
    }
}动态创建代理对象的类(代理类,使用反射机制):
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyHandler implements InvocationHandler {
    /**
     *
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    /**
     *目标对象
     */
    private Object target;
    /**
     */
    public Object newProxyInstance(Object target){
       this.target = target;
       Object result = Proxy.newProxyInstance(target.getClass().getClassLoader(),
               target.getClass().getInterfaces(),this);
       return result;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //TODO原对象方法调用添加的预处理逻辑
        Object ret = null;
        try{
            //调用目标方法
            ret = method.invoke(target, args);
        }catch (Exception e){
            //log("调用{}.{}发生异常", target.getClass().getName(), method.getName(), e);
            throw e;
        }
        return ret;
    }
}客户端类:
import lombok.extern.slf4j.Slf4j;
import java.util.logging.Logger;
public class Client {
    public static void main(String[] args){
        System.out.println("开始");
        ProxyHandler handler = new ProxyHandler();
        Subject subject = (Subject) handler.newProxyInstance(new ConcreteSubject());
        subject.request();
        System.out.println("结束");
    }
}
运行结果:

 
  
  
  
  
 
 
  
 