天天看点

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