## 动态性
可以在运行的时候修改类。比如加应该 新方法, 或者在方法里面加新的东西
其中重点在于**运行的时候修改**,而不是在编译时
我们知道一个类在装入到了方法区之后还怎么修改了 ?
为什么人们有这个要求呢?
因为人们要以声明的方式编程。比如写完了代码以后有这样的需求:
* 在某些函数调用前后加上日志记录
* 给某些函数加上事务的支持
* 给某些函数加上权限控制
这些需求通用的,如果每个函数都实现一遍,重复代码太多了。而且很多时候代码是别人写的,只有class文件。
所以人们想到在XML文件声明一下,比如对于 com.coderising 这个 package 下所有以 add 开头的方法,在执行之前都要调用 Logger.startLog() 方法, 在执行之后都要调用 Logger.endLog() 方法。
或者对于所有以 DAO 结尾的类,所有的方法执行之前都要调用 TransactionManager.begin(),执行之后都要调用 TransactionManager.commit(), 如果抛出异常的话调用 TransactionManager.rollback()。
人们开发了一个叫 AOP 的东西,能够读取这个 XML 中的声明, 并且能够找到那些需要插入日志的类和方法, 接下来就需要修改这些方法了。 但是 Java 不允许修改一个已经被加载或者正在运行的类,
## Java 动态代理
虽然不能修改现有的类,但是可以在运行时动态的创建新的类啊,比如有个类 HelloWorld:
现在的问题是要在 sayHello() 方法中调用 Logger.startLog(), Logger.endLog() 添加上日志, 但是这个 sayHello() 方法又不能修改了!

可以动态地生成一个新类,让这个类作为 HelloWorld 的代理去做事情(加上日志功能)

这个 HelloWorld 代理也实现了 IHelloWorld 接口。 所以在调用方看来,都是 IHelloWorld 接口,并不会意识到底层已经改变了。
人们需要写一个类来告诉我们具体把 Logger 的代码加到什么地方, 这个类必须实现java定义的 InvocationHandler 接口,该接口中有个叫做 invoke 的方法就是他们写扩展代码的地方

无非就是在调用真正的方法之前先调用 Logger.startLog(), 在调用之后在调用 Logger.end(), 这就是对方法进行拦截了
也就是说这个 LoggerHandler 充当了一个中间层, 我们自动化生成的类 $HelloWorld100 会调用它,把 sayHello 这样的方法调用传递给他 (上图中的 method 变量),于是 sayHello() 方法就被添加上了 Logger 的 startLog() 和 endLog() 方法

这是因为在 Proxy.newProxyInstance(....) 这里,就是动态地生成了一个类嘛, 这个类对臣民们来说是动态生成的, 也是看不到源码的
在运行时,在内存中生成了一个新的类,这个类在调用 sayHello() 或者 add() 方法的时候, 其实调用的是 LoggerHanlder 的 invoke 方法, 而那个 invoke 就会拦截真正的方法调用,添加日志功能了
