## 動態性
可以在運行的時候修改類。比如加應該 新方法, 或者在方法里面加新的東西
其中重點在于**運行的時候修改**,而不是在編譯時
我們知道一個類在裝入到了方法區之后還怎么修改了 ?
為什么人們有這個要求呢?
因為人們要以聲明的方式編程。比如寫完了代碼以后有這樣的需求:
* 在某些函數調用前后加上日志記錄
* 給某些函數加上事務的支持
* 給某些函數加上權限控制
這些需求通用的,如果每個函數都實現一遍,重復代碼太多了。而且很多時候代碼是別人寫的,只有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 就會攔截真正的方法調用,添加日志功能了