戴着假发的程序员出品 抖音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修饰的。