运行时动态生成Java类
程序启动后,根据代码逻辑,在执行代码过程中,动态生成字节码文件并以进行相应的类装载等。他与程序启动前,我们编写代码,生成.class,JVM装载类这个过程不同。动态生成意味着原本没有相应.class文件,是我们后来自己生成的.class,然后装载。
JVM之所以能够这样是因为,凡是正确的、符合相应结构的字节码数据,都可以平滑的向JVM中转换(也就是被JVM加载),所以甚至是我们动态的手写字节码都是可以的。
当然,动态生成JAVA类,我们通常是采用如cglib、ASM等类库来实现。
动态生成JAVA类这项技术被运用于很多地方,如:Mock、ORM、IOC等

JAVA的动态代理也是以此构建的
在讲动态代理前,先回顾一下静态代理

//接口
public interface HelloInterface {
    void sayHello();
}

//被代理的类
public class Hello implements HelloInterface{
    @Override
    public void sayHello() {
        System.out.println("Hello zhanghao!");
    }
}

//进行代理的类
public class HelloProxy implements HelloInterface{
    private HelloInterface helloInterface = new Hello();
    @Override
    public void sayHello() {
        System.out.println("Before invoke sayHello" );
        helloInterface.sayHello();
        System.out.println("After invoke sayHello");
    }
}

//主程序
public static void main(String[] args) {
        HelloProxy helloProxy = new HelloProxy();
        helloProxy.sayHello();
    }

我们可以看出,由于代理只能为一个类服务,如果需要代理的类很多,那么就需要编写大量的代理类,比较繁琐。所以,JAVA在动态代理的原理中,动态生成.class字节码文件从而创建了一个实现了接口的被代理类(即被代理类和代理类都实现了这个接口),然后,通过反射调用这个被代理类的相关方法,并在该方法前后实现其他操作(即执行我们插入到被代理类方法前后的其他操作),当然,以上的操作被封装成了,我们只需要向其中以参数的形式,放入我们的被代理类即可。

// 它不是代理类,更不是被代理类,但他包含了代理类要执行的操作
public class ProxyHandler implements InvocationHandler{
    private Object object;
    public ProxyHandler(Object object){
        this.object = object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before invoke "  + method.getName());
        method.invoke(object, args);
        System.out.println("After invoke " + method.getName());
        return null;
    }
}

// 主程序
public static void main(String[] args) {
      System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

      HelloInterface hello = new Hello();
      
      InvocationHandler handler = new ProxyHandler(hello);
      
      // 这句代码动态生成了一个代理类 生成的这个代理类中肯定包含了被代理类对象并且实现了被代理对象实现的接口
      HelloInterface proxyHello = (HelloInterface) Proxy.newProxyInstance(hello.getClass().getClassLoader(), hello.getClass().getInterfaces(), handler);

      proxyHello.sayHello();
  }
  输出:
  Before invoke sayHello
  Hello zhanghao!
  After invoke sayHello

以上是JDK Proxy(即JDK自身提供的动态代理)
cglib动态代理采取的是创建目标类的子类的方式,因为是子类化,我们可以达到近似使用被调用者本身的效果。