小言_互联网的博客

AOP中JDK代理与CGLib代理的区别

467人阅读  评论(0)

目录

一、环境配置

二、如何启动两种代理类

三、JDK代理类与CGlib代理类区别

1.证明

2.影响


一、环境配置

首先,创建service层方法div,及其代理类MethodAOP:


  
  1. package club.affengkuang.computer.service;
  2. import org.springframework.stereotype.Service;
  3. //服务层
  4. @Service
  5. public class ComputerService implements IComputerService{
  6. public int div(int a, int b) {
  7. return a/b;
  8. }
  9. }

  
  1. package club.affengkuang.aop;
  2. import org.aspectj.lang.JoinPoint;
  3. import org.aspectj.lang.Signature;
  4. //代理类
  5. public class MethodAOP {
  6. public void before(JoinPoint jp) {
  7. Object [] args = jp.getArgs();
  8. Signature signature = jp.getSignature();
  9. String name = signature.getName();
  10. System.out.println( "the "+name+ " method begins.");
  11. System.out.println( "the "+name+ " method param ["+args[ 0]+ ","+args[ 1]+ "]");
  12. }
  13. }

 application.xml文件的配置如下:


  
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context= "http://www.springframework.org/schema/context"
  5. xmlns:aop= "http://www.springframework.org/schema/aop"
  6. xmlns:p= "http://www.springframework.org/schema/p"
  7. xmlns:tx= "http://www.springframework.org/schema/tx"
  8. xsi:schemaLocation= "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
  9. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
  10. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
  11. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
  12. <context:component-scan base-package="club.affengkuang"> </context:component-scan>
  13. <bean id="ma" class="club.affengkuang.aop.MethodAOP"> </bean>
  14. <aop:config>
  15. <!-- 定义一个aop表达式 -->
  16. <aop:pointcut expression="execution(public int club.affengkuang.computer.service.ComputerService.*(..))" id="pc"/>
  17. <!-- 设置一个切面类 -->
  18. <aop:aspect ref="ma">
  19. <aop:before method="before" pointcut-ref="pc"/>
  20. </aop:aspect>
  21. </aop:config>
  22. </beans>

二、如何启动两种代理类

在如下测试类中调用div方法,并打印代理类类名,得到的该类名就是默认的JDK代理类:


  
  1. package club.affengkuang.test;
  2. import org.springframework.context.support.ClassPathXmlApplicationContext;
  3. import club.affengkuang.computer.service.IComputerService;
  4. public class Test {
  5. public static void main(String[] args) {
  6. ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext( "application.xml");
  7. IComputerService computerService = applicationContext.getBean(IComputerService.class);
  8. System.out.println(computerService.div( 1, 1));
  9. System.out.println(computerService.getClass().getName());
  10. applicationContext.close();
  11. }
  12. }

启动CGlib代理类,只需在application.xml文件中aop:config标签头部将proxy-target-class属性赋值为true即可,该属性默认值为false,也就是默认使用JDK代理类,赋值为true后使用的便是CGlib代理类:


  
  1. <aop:config proxy-target-class="true">
  2. <!-- 定义一个aop表达式 -->
  3. <aop:pointcut expression="execution(public int club.affengkuang.computer.service.ComputerService.*(..))" id="pc"/>
  4. <!-- 设置一个切面类 -->
  5. <aop:aspect ref="ma">
  6. <aop:before method="before" pointcut-ref="pc"/>
  7. </aop:aspect>
  8. </aop:config>

这时再调用测试类打印代理类类名,得到的便是CGlib代理类类名: 

三、JDK代理类与CGlib代理类区别

JDK代理类:代理类和目标类无直接继承关系,代理类实现的是目标类实现的接口

CGlib代理类:直接继承自目标类

1.证明

如下:首先设置成JDK代理类,并在测试类中输出代理类所实现的接口,得到了目标类所实现的IComputerService接口:


  
  1. package club.affengkuang.test;
  2. import org.springframework.context.support.ClassPathXmlApplicationContext;
  3. import club.affengkuang.computer.service.IComputerService;
  4. public class Test {
  5. @SuppressWarnings( "rawtypes")
  6. public static void main(String[] args) {
  7. ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext( "application.xml");
  8. IComputerService computerService = applicationContext.getBean(IComputerService.class);
  9. Class clazz = computerService.getClass();
  10. for(Class c:clazz.getInterfaces()) {
  11. System.out.println(c);
  12. }
  13. applicationContext.close();
  14. }
  15. }

再将其设置成CGlib代理类,并在测试类中打印所继承的父类,得到了目标类:


  
  1. package club.affengkuang.test;
  2. import org.springframework.context.support.ClassPathXmlApplicationContext;
  3. import club.affengkuang.computer.service.IComputerService;
  4. public class Test {
  5. @SuppressWarnings( "rawtypes")
  6. public static void main(String[] args) {
  7. ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext( "application.xml");
  8. IComputerService computerService = applicationContext.getBean(IComputerService.class);
  9. Class clazz = computerService.getClass();
  10. System.out.println(clazz.getSuperclass());
  11. applicationContext.close();
  12. }
  13. }

2.影响

CGlib代理类直接继承自目标类,也就意味着在IOC容器中既可以通过目标类实现的接口获取代理类,也可以通过目标类获取代理类,将第13行getBean方法的参数改为通过目标类获取,同样可以得到代理类: 


  
  1. package club.affengkuang.test;
  2. import org.springframework.context.support.ClassPathXmlApplicationContext;
  3. import club.affengkuang.computer.service.ComputerService;
  4. import club.affengkuang.computer.service.IComputerService;
  5. public class Test {
  6. @SuppressWarnings( "rawtypes")
  7. public static void main(String[] args) {
  8. ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext( "application.xml");
  9. IComputerService computerService = applicationContext.getBean(ComputerService.class);
  10. System.out.println(computerService.getClass().getName());
  11. applicationContext.close();
  12. }
  13. }

而JDK代理类和目标类无直接继承关系,所以只能通过接口获取代理类,将proxy-target-class属性改为false,即使用JDK代理类,再执行上述测试类,则会抛出异常:

 

 

 


转载:https://blog.csdn.net/DangerousMc/article/details/104920729
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场