天天看點

spring應用手冊-AOP(注解)-(6)-springAOP的代理方式

戴着假發的程式員出品 抖音ID:戴着假發的程式員 歡迎關注

springAOP的代理方式

spring應用手冊(第三部分)

曾經有人問過我,springAOP到低是JDK代理還是CGLib代理。現在我們就來聊聊這個問題。

其實預設情況下spring不确定使用什麼方式實作動态代理,如果你的目标類實作了任何一個或者多個接口,那麼spring預設使用JDK代理實作動态代理,如果你的目标類沒有實作任何接口,那麼spring會使用CGLib完成動态代理。我想這個是為什麼就不在這裡進行講解了。

看案例:

就在HelloWorld的案例中進行修改,我們Hellowrold案例中的BookService是沒有實作任何接口的。

我們修改測試類,添加斷點進行檢視:

@Test
public void testAopProxy(){
    AnnotationConfigApplicationContext ac =
            new AnnotationConfigApplicationContext(Appconfig.class);
    //擷取工廠對象
    ConfigurableListableBeanFactory beanFactory = ac.getBeanFactory();//斷點
    Object bookService = beanFactory.getSingleton("bookService");
    System.out.println(bookService);
}
           

檢視beanFactory中的singletonObject中的bookService對象:

spring應用手冊-AOP(注解)-(6)-springAOP的代理方式

我們會發現這裡是通過CGLib代理的。

我們再添加一個接口:

/**
 * @author 戴着假發的程式員
 * 
 * @description
 */
public interface IBookService {
    public void saveBook(String title);
}
           

讓我們的BookService實作這個接口:

/**
 * @author 戴着假發的程式員
 * 
 * @description
 */
@Component
public class BookService implements IBookService{
    @Override
    public void saveBook(String title){
        System.out.println("儲存圖書:"+title);
    }
}
           

再執行上面的測試:

spring應用手冊-AOP(注解)-(6)-springAOP的代理方式

這是我們發現就不再是CGLib代理了。

當然我們也可以通過配置強行要求spring使用CGLib進行動态代理,因為我知道CGLib不止可以對沒有實作接口的類進行代理,而且可以對實作接口的類進行代理。

我們可以通過修改 @EnableAspectJAutoProxy 的屬性 proxyTargetClass值為true,強行要求spring使用CGLib進行代理。

/**
 * @author 戴着假發的程式員
 * 
 * @description
 */
@Configuration
@ComponentScan("com.st.dk.demo7")
@EnableAspectJAutoProxy(proxyTargetClass = true) //開啟@AspectJ 支援
public class Appconfig {
}
           

屬性proxyTargetClass預設值是false,如果修改為true,就是要求spring強行使用CGLib進行代理。我們繼續執行上面的測試會發現又會是CGLib代理的對象。

但是CGLib代理也有問題,我們知道CGLib是通過繼承的方式實作代理的,如果我們的方法是final修飾的那麼就無法重寫,自然就無法代理了。當然大部分情況下我們的業務方法可能都不是final修飾的。