茫茫網海中的冷日 - 對這文章發表回應
茫茫網海中的冷日
         
茫茫網海中的冷日
發生過的事,不可能遺忘,只是想不起來而已!
 恭喜您是本站第 1729843 位訪客!  登入  | 註冊
主選單

Google 自訂搜尋

Goole 廣告

隨機相片
PIMG_00227.jpg

授權條款

使用者登入
使用者名稱:

密碼:


忘了密碼?

現在就註冊!

對這文章發表回應

發表限制: 非會員 可以發表

發表者: 冷日 發表時間: 2019/4/19 8:15:31

略談 cglib

Java 本身的動態代理,必須要基於介面定義,若類別並沒有實作特定介面,就無法使用 Java 動態代理機制,這時可以透過 cglib(Code Generation Library),它的底層基於 ASM,可於執行時期修改位元組碼、動態生成代理物件。

若要將〈 動態代理〉的專案範例改用 cglib,可以在 gradle.build 中加入相依:


compile 'cglib:cglib-nodep:'3.2.9'

接著實作一個攔截器,它實作了 MethodInterceptor


package cc.openhome.interceptor;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.logging.Logger;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class LoggingInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object target, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
Logger.getLogger(target.getClass().getName())
.info(String.format("%s.%s(%s)",
target.getClass().getName(), method.getName(), Arrays.toString(args)));
return proxy.invokeSuper(target, args);
}
}

然後 AppConfig 基於 cglib 來建立代理物件:


package cc.openhome;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import cc.openhome.interceptor.LoggingInterceptor;
import cc.openhome.model.AccountDAO;
import net.sf.cglib.proxy.Enhancer;
@Configuration
@ComponentScan
public class AppConfig {
@Autowired
@Qualifier("accountDAOJdbcImpl")
private AccountDAO accountDAO;
@Autowired
private DataSource dataSource;
@Bean(destroyMethod="shutdown")
public DataSource dataSource(){
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:schema.sql")
.addScript("classpath:testData.sql")
.build();
}
@Bean
public AccountDAO accountDAO() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(accountDAO.getClass());
enhancer.setCallback(new LoggingInterceptor());
return (AccountDAO) enhancer.create(
new Class[] {DataSource.class},
new Object[] {dataSource}
);
}
}

在進行動態代理時,Spring 底層預設會採用 Java 動態代理,若目標對象沒有實作介面則改用 cglib,實際上,AOP 是個概念,各廠商會有各自的實現,為此, AOP Alliance 定義了一套介面標準, MethodInterceptor 在 AOP Alliance 的定義則是:


package org.aopalliance.intercept;
public interface MethodInterceptor {
Object invoke(MethodInvocation methodInvocation) throws Throwable;
}

若使用 Spring AOP,你也可以實作這個介面,這部份可參考我舊版文件中的 AroundAdvice 中的範例。


原文出處:略談 cglib
內容圖示
url email imgsrc image code quote
樣本
bold italic underline linethrough   












 [詳情...]
validation picture

注意事項:
預覽不需輸入認證碼,僅真正發送文章時才會檢查驗證碼。
認證碼有效期10分鐘,若輸入資料超過10分鐘,請您備份內容後,重新整理本頁並貼回您的內容,再輸入驗證碼送出。

選項

Powered by XOOPS 2.0 © 2001-2008 The XOOPS Project|