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修饰的。