3.6 springAOP的代理方式

戴着假发的程序员出品  抖音ID:戴着假发的程序员  欢迎关注

[查看视频教程]

曾经有人问过我,springAOP到低是JDK代理还是CGLib代理。现在我们就来聊聊这个问题。

其实默认情况下spring不确定使用什么方式实现动态代理,如果你的目标类实现了任何一个或者多个接口,那么spring默认使用JDK代理实现动态代理,如果你的目标类没有实现任何接口,那么spring会使用CGLib完成动态代理。我想这个是为什么就不在这里进行讲解了。

看案例:

就在HelloWorld的案例中进行修改,我们Hellowrold案例中的BookService是没有实现任何接口的。

我们修改测试类,添加断点进行查看:

1 @Test
2 public void testAopProxy(){
3     AnnotationConfigApplicationContext ac =
4             new AnnotationConfigApplicationContext(Appconfig.class);
5     //获取工厂对象
6     ConfigurableListableBeanFactory beanFactory = ac.getBeanFactory();//断点
7     Object bookService = beanFactory.getSingleton("bookService");
8     System.out.println(bookService);
9 }

查看beanFactory中的singletonObject中的bookService对象:

我们会发现这里是通过CGLib代理的。

我们再添加一个接口:

1 /**
2  * @author 戴着假发的程序员
3  * 
4  * @description
5  */
6 public interface IBookService {
7     public void saveBook(String title);
8 }

让我们的BookService实现这个接口:

 1 /**
 2  * @author 戴着假发的程序员
 3  * 
 4  * @description
 5  */
 6 @Component
 7 public class BookService implements IBookService{
 8     @Override
 9     public void saveBook(String title){
10         System.out.println("保存图书:"+title);
11     }
12 }

再执行上面的测试:

这是我们发现就不再是CGLib代理了。

 

当然我们也可以通过配置强行要求spring使用CGLib进行动态代理,因为我知道CGLib不止可以对没有实现接口的类进行代理,而且可以对实现接口的类进行代理。

我们可以通过修改 @EnableAspectJAutoProxy 的属性 proxyTargetClass值为true,强行要求spring使用CGLib进行代理。

 1 /**
 2  * @author 戴着假发的程序员
 3  * 
 4  * @description
 5  */
 6 @Configuration
 7 @ComponentScan("com.st.dk.demo7")
 8 @EnableAspectJAutoProxy(proxyTargetClass = true) //开启@AspectJ 支持
 9 public class Appconfig {
10 }

属性proxyTargetClass默认值是false,如果修改为true,就是要求spring强行使用CGLib进行代理。我们继续执行上面的测试会发现又会是CGLib代理的对象。

 

但是CGLib代理也有问题,我们知道CGLib是通过继承的方式实现代理的,如果我们的方法是final修饰的那么就无法重写,自然就无法代理了。当然大部分情况下我们的业务方法可能都不是final修饰的。

posted @ 2020-10-17 17:13  戴着假发的程序员0-1  阅读(119)  评论(0编辑  收藏  举报