在實習期間遇到最多的兩個框架就是spring和paoding-rose了,所以看完spring源碼分析的書,我就迫不及待的開始找paoding-rose的書了。可惜沒找到,所以就自己動手分析吧。
spring源碼分析的書可以在這裏下載:
http://download.csdn.net/download/qq523786283/9946552
1.正文
paoding-rose框架包含很多子框架,而我實習的公司項目中只用到paoding-rose-jade。所以我這裏分析的是paoding-rose-jade。
我選擇的分析的入口是下面圖片裏選擇的類:
理由是我們可以通過單元測試類更輕鬆的知道代碼作者的設計意圖。
先貼出單元測試源碼:
/**
* 通過集成DAO和JadeFactory,驗證 {@link DataSources}的可用
*
* @author 王志亮 [[email protected]]
*
*/
public class DataSourcesTest {
@DAO
interface UserDAO {
@SQL("create table user (id int, name varchar(200));")
void createTable();
@SQL("insert into user (id, name) values(:1, :2);")
void insert(int id, String name);
@SQL("select name from user where id=:1")
String getName(int id);
@SQL("select name from user order by id asc")
String[] findNames();
}
// init方法負責初始化dao
private UserDAO dao;
@Before
public void init() {
DataSource dataSource = DataSources.createUniqueDataSource();
JadeFactory factory = new JadeFactory(dataSource);
dao = factory.create(UserDAO.class);
dao.createTable();
dao.insert(1, "zhiliang1");
dao.insert(2, "zhiliang2");
}
@Test
public void testGetName() {
Assert.assertEquals("zhiliang1", dao.getName(1));
}
@Test
public void testFindNames() {
String[] names = dao.findNames();
Assert.assertEquals(2, names.length);
Assert.assertEquals("zhiliang1", names[0]);
Assert.assertEquals("zhiliang2", names[1]);
}
}
相信用過paoding-rose-jade都會對下面這段代碼感到非常的熟悉,沒用過的也能清晰知道它定義了一個接口。唯有@DAO
和@SQL
註解需要我們推測它們的用途。
@DAO
interface UserDAO {
@SQL("create table user (id int, name varchar(200));")
void createTable();
@SQL("insert into user (id, name) values(:1, :2);")
void insert(int id, String name);
@SQL("select name from user where id=:1")
String getName(int id);
@SQL("select name from user order by id asc")
String[] findNames();
}
這些推測都暫且放下,我先看到被 @Before
註解標記的 init()
方法。根據junit4單元測試類的規則,每個 @Test
標記的方法運行前都有運行一次被 @Before
註解標記的方法。
在init()
中
1.生成一個數據源對象(DataSource)
2.通過數據源對象(DataSource)生成一個工廠對象(JadeFactory)
3.通過調用JadeFactory對象的create(UserDAO.class)
方法,獲得一個實現UserDao接口的對象。
4.接下來就是我們熟悉的數據庫操作了。
@Before
public void init() {
DataSource dataSource = DataSources.createUniqueDataSource();
JadeFactory factory = new JadeFactory(dataSource);
dao = factory.create(UserDAO.class);
dao.createTable();
dao.insert(1, "zhiliang1");
dao.insert(2, "zhiliang2");
}
看到第3步時,相信大家都有一個相同的問題:
我們沒實現UserDAO接口,何來一個實現UserDAO接口的對象呢?
對於這個,我給出的推測是paoding-rose-jade使用了動態代理。
爲什麼說是“推測”呢?因爲我是抱着學習的心態寫這篇博客的,無論對錯都是我分析的過程,也就是說我是一邊開始學習paoding-rose-jade框架源碼一邊寫博客的。
現在就讓我們一起解答這個問題吧。
這時選擇單元測試類作爲入口的另一個好處就顯現出來了—我們可以通過調試代碼來解決我們的問題。
首現如圖下個斷點,並debug:
從調試信息中我們可以看到dao對象在內存中的信息是{$Proxy3@1308}
,從名稱可以推測它是一個代理對象,當然這並不嚴謹。
所以我們按F7跟入createTable()
方法繼續調試。如下:
跟進去後我們發現我們到了一個陌生而又熟悉的invoke()
方法.
沒錯這個是java動態代理的方法,這證明了我們的推測是正確的。沒學過java動態代理的同學可能會感到一頭霧水,這時候就需要你們自己去百度或谷歌一下了。
從調試信息中我們可以看到invoke()
方法中傳進去的Proxy對象在內存中的信息是{$Proxy3@1308}
,所以這個就是前面的dao對象。
接下來的內容就下一篇再繼續吧。