戴着假發的程式員出品 抖音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對象:
我們會發現這裡是通過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);
}
}
再執行上面的測試:
這是我們發現就不再是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修飾的。